home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / UCRASM25.ARJ / STDLIB.TXT < prev    next >
Text File  |  1991-12-26  |  221KB  |  6,669 lines

  1. ***************************************************************************
  2. ***************************************************************************
  3.  
  4.  
  5.  
  6. The UCR Standard Library for Assembly Language Programmers,
  7. Written By Randall Hyde and others, is
  8.  
  9.   sssssss      ss     ss       ss       sssssss     sssssss
  10.   ss           ss     ss      ssss      ss    ss    ss
  11.   ss           ss     ss     ss  ss     ss    ss    ss
  12.   sssssss      sssssssss    ssssssss    sssssss     sssss        ssssssss
  13.        ss      ss     ss    ss    ss    ss  ss      ss
  14.        ss      ss     ss    ss    ss    ss   ss     ss
  15.   sssssss      ss     ss    ss    ss    ss    ss    sssssss
  16.  
  17.  
  18.  
  19.   ww                  ww       ww       sssssss     sssssss
  20.    ww                ww       wwww      ss    ss    ss
  21.     ww      ww      ww       ww  ww     ss    ss    ss
  22.      ww    wwww    ww       wwwwwwww    sssssss     sssss
  23.       ww  ww  ww  ww        ww    ww    ss  ss      ss
  24.        wwww    wwww         ww    ww    ss   ss     ss
  25.         ww      ww          ww    ww    ss    ss    sssssss
  26.  
  27.  
  28.  
  29.  
  30. We do not want any registration fees for this software.
  31.  
  32. Now for the catch...  It is more blessed to give than to receive.  
  33. If this software saves you time and effort and you enjoy using it, 
  34. our lives will be enriched knowing that others have appreciated our work.  
  35. We would like to share this wonderful feeling with you.  If you like this 
  36. software and use it, we would like you to contribute at least one routine to 
  37. the library.  Perhaps you think this library has some neat-o routines in it.  
  38. Imagine how nice it would become if everyone used their imagination to 
  39. contribute something useful to it.
  40.  
  41. We hereby release this software to the public domain.  You can use it in any
  42. way you see fit.  However, we would appreciate it if you share this software 
  43. with others as much as it has been shared it with you.  That is not to suggest
  44. that you give away software you have written with this package (We're not 
  45. quite as crazy as Richard Stallman, bless his heart), but if someone else would 
  46. like a copy of this library, please help them out.  Naturally, we would be 
  47. tickeled pink to receive credit in software that uses these routines (which is 
  48. the honorable thing to do) but we understand the way many corporations operate 
  49. and won't be terribly put off if you use it without giving due credit.  
  50.  
  51. Enjoy!
  52.  
  53. If you have comments, bug reports, new code to contribute, etc., you can 
  54. reach us through:
  55.  
  56.         rhyde                (On BIX).
  57.         rhyde@ucrmath.ucr.edu        (On Internet).
  58.  
  59. or
  60.  
  61.         Randall Hyde
  62.         Dept of Computer Science
  63.         122 University Office Bldg
  64.         University of California
  65.         Riverside, Ca. 92521
  66.  
  67.  
  68. COMMENTS ABOUT THE CODE:
  69. ************************
  70.  
  71. Please don't expect super optimal code here.  Most of it is fairly mediocre 
  72. (from a size/speed point of view).  Hopefully, you'll agree, it's the idea 
  73. that counts.  If you do not like something I have done, you have got the 
  74. sources -- have at it.  (Of course, it would be appreciated if you would
  75. send any modifications to one of the E-MAIL addresses above.)
  76.  
  77.  
  78. ************************************ NOTE ************************************
  79.  
  80. Please understand the purpose of this code!  This library is here to make
  81. assembly language programming easy.  The nature of this library encourages
  82. people to write code in a fashion similar to that employed when they write
  83. programs in a high level language like C.  While this familiar style of
  84. programming does make the task easier, it is not the most appropriate
  85. approach to use when flat-out performance is what you're seeking.  "C code
  86. written with MOV instructions" is never as fast as pure assembly language
  87. code employing the proper programming paradigm.  Why mention this?  Well,
  88. some readers may have heard about assembly language's legendary performance
  89. and they're expecting to achieve that using this library.  While programs
  90. written with this library may very well run faster than a comparable program
  91. written in a HLL, you will not get fantastic performance improvement until
  92. you stop thinking in HLLs and starting "thinking" in assembly.  The purpose
  93. of this library is to help you *avoid* thinking in assembly language.  There-
  94. fore, this code will not help you achieve those fantastic performance levels
  95. you've been hearing about; indeed, this library may stand in the way of that
  96. goal.  It's not that these routines are terribly slow, mind you.  They just
  97. encourage an inappropriate programming style if speed is what you're after.
  98.  
  99. On the other hand, since only 10-20% of the code of any given program
  100. represents the time critical stuff (an argument long employed by HLL
  101. supporters), there is nothing wrong with judicious use of this code within
  102. a program that has to be fast.  As usual, if performance is your primary
  103. goal, you must study the problem and the program you generate very carefully
  104. to isolate the time critical portions.  If you are interested in high-
  105. performance programming at the "micro-algorithm" level, you should take a look
  106. at Michael Abrash's text "Zen of Assembly."  This excellent book will explain
  107. many ways to improve the performance of your code at the sub-algorithm level
  108. (where assembly language really shines).
  109.  
  110.  
  111.  
  112. COMMENTS ABOUT THIS DOCUMENTATION:
  113. **********************************
  114.  
  115. You will have to forgive us for the inconsistent style appearing throughout
  116. this document.  Keep in mind that this document has been prepared by many
  117. different people.  Keeping the styles consistent is a time consuming and
  118. difficult task.
  119.  
  120. Whenever a routine's description claims that the flags are not affected,
  121. you should not interpret this to mean that the routine preserves the flags.
  122. Most routines do *not* preserve any of the flags.  Such a statement simply
  123. means that the routine does not *explicitly* return a value in one (or more)
  124. of the flag bits.
  125.  
  126. Note that proper credit has been given to the author of each of the various
  127. routines appearing in this library *except* for those written by Randall
  128. Hyde.  All routines without an author by-line were probably written by
  129. Randall Hyde (unless we screwed up somewhere and forgot to put a name
  130. in the documentation).  Most of these routines were tested and documented
  131. by various students in Randy Hyde's CS 13 (assembly language) and CS 191X /
  132. CS 185 courses (Commercial Software Development).  There are too many names
  133. to mention here, but these students definitely deserve the credit for locating
  134. numerous bugs in the code, providing many suggestions, and doing other work.
  135.  
  136.  
  137. =============================================================================
  138.  
  139. Version History:
  140.  
  141. Version 0.0-     Initial release as "Randy Hyde's Standard Library for 80x86
  142.         Assembly Language programmers"
  143.  
  144. Version 1.0-    Initial release as "UCR Standard Library..."  CS 191X
  145.         students did some testing and documentation in this release.
  146.  
  147. Version 2.0-    More testing on several routines.  Added floating point
  148.         library and several other routines.
  149.  
  150. Version 2.1-    Fixed *MAJOR* bugs in floating point package.  Added
  151. 11-1-91        several new routines.  Included new "TEST" files with
  152.         the library.  Also included SHELL.ASM file inadvertently
  153.         left out of Version 2.0.
  154.  
  155. Version 2.2-    Made some minor modifications to puth, putl, ltoa, and htoa
  156. 11-14-91    as per suggestions made by David Holm and Terje Maithesen
  157.  
  158. Version 2.3-    Made a small but *major* modification to the stdlib.a and
  159. 11-22-91    stdlib.a6 files to force library calls into the STDGRP group.
  160.         Otherwise the linker substitued bad segment addresses for
  161.         the far calls to the library routines.  A real problem when
  162.         accessing variables in StdData.
  163.  
  164. Version 2.4-    Yet more changes to fix the stupid MASM group/segment:offset
  165. 12-7-91        bug.  Made various changes to the STDLIB.A file.  Also fixed
  166.         a problem in the FP routines- forgot to declare sl_sefpa
  167.         public.  Finally, created batch file to automatically unpack
  168.         everything from DOS (assuming presence of PKUNZIP somewhere
  169.         in the current path).
  170.  
  171. Version 2.5-    Some new macros (DOS, ExitPgm), fixed a problem with the
  172. 12-25-91    PUTI routine, added some SmartArray items.  Also added the
  173.         GetEnv routine.
  174.  
  175.  
  176.  
  177. ==============================================================================
  178.  
  179.  
  180. ROUTINES WE WOULD LIKE TO HAVE:
  181. *******************************
  182.  
  183. If you're interested in adding some routines to this
  184. package, GREAT!  Here are some suggestions.
  185.  
  186. 1) Routines which manipulate directories (read/write/etc.)
  187. 2) A regular expression interpreter.
  188. 3) Length-prefixed strings package.
  189. 4) A graphics package.
  190. 5) An object-oriented programming class library.
  191. 6) Just about anything else appearing in a HLL "standard" library.
  192. If you've got any ideas, we would  love to discuss them with you.  The best
  193. way to reach us is through the E-MAIL addresses above.
  194.  
  195.  
  196. MISSING ROUTINES TO BE SUPPLIED IN THE FUTURE:
  197. **********************************************
  198.  
  199. Character strings:
  200. trim-        Removes trailing blanks from a string.
  201. blkdel-        Removes leading blanks from a string.
  202. translit-    Transliterates characters in a string based on a translation
  203.         table.
  204.  
  205.  
  206. Pattern matching and character sets:
  207. span-        Skips through a sequence of characters in a string which
  208.         belong to a character set.
  209. break-        Skips through a sequence of characters in a string which do not
  210.         belong to a character set.
  211. any-        Skips over a character if it is a member of a set.
  212. notany-        Skips over a character in a string if it is not a member
  213.         of a set.
  214. skip-        Skips "n" characters in the string.
  215. tab-        Matches up to the nth character in a string.
  216. rtab-        Matches up to the nth character from the end of a string.
  217. pos-        Matches if we are currently at the nth position in a string.
  218. rpos-        Matches if we are at the nth position from the end of the
  219.         string.
  220. mark-        Marks a position in a string during pattern matching
  221. grab-        Copies everything from the last mark and creates a new string 
  222.         on the stack from this substring.
  223. match-        Initialize pattern matching system.
  224. alternate-    Try an alternative if the current pattern does not match.
  225. arb-        Skip over an arbitrary number of characters in a match.
  226. replace-    Replace a substring from the last mark to the current 
  227.         position with some other string.
  228. fail-        Force a match failure.
  229. succeed-    Force a match success.
  230.  
  231.  
  232.     Memory Manager Package
  233. Memavail-    Largest block of free memory available on the heap.
  234. Memfree-    Total amount of free space on the heap.
  235. BlockSize-    Returns the size of the memory block which es:di points at.
  236.  
  237.  
  238.     Process Manager Package
  239. CoCall-        Call a coroutine.  
  240. CoInit-        Initialize a coroutine.
  241. CoRet-        Quit a coroutine.
  242.  
  243.  
  244. HOW TO USE THE STANDARD LIBRARY:
  245. ********************************
  246.  
  247. When you are ready to begin programming with the library, you should
  248. copy the shell.asm file, provided in the package, to another file in
  249. which you will be working, i.e. myprog.asm.  The shell.asm file sets
  250. up the machine (segments, etc.) as the UCR Standard Library expects
  251. them.  Results are undefined for other setups.  Therefore, I strongly
  252. suggest, that when you begin using these routines, you follow the
  253. shell.asm format.  Later, when you are familiar with the software,
  254. you may wish to create your own shell.asm file, but it is wise to
  255. initially use the one provided.  The shell.asm file has comments which
  256. tell you where to place your code, variables, etc.
  257.  
  258. There is an include file, stdlib.a (stdlib.a6 for MASM 6.0 users), which
  259. you should include in every assembly you perform which calls the stdlib
  260. routines.  SHELL.ASM already includes this file.  *YOU MUST PLACE THE
  261. INCLUDE STATEMENT OUTSIDE OF ANY SEGMENTS IN YOUR PROGRAM*.  Preferably
  262. as the first line of your program (just like SHELL.ASM).  If you place
  263. this include directive inside a segment, certain assemblers/linkers
  264. (especially MASM) will not properly assemble and link your programs.
  265. They will assemble and link without error, but the resulting program
  266. will not execute correctly.
  267.  
  268. The STDLIB.A file contains macros you can use to call each of the routines
  269. in the standard library.  For example, to call PRINTF you would use the
  270. statement
  271.         printf
  272.         db    "format string",0
  273.         db    other,vars
  274.  
  275. rather than "calling" printf.  Printf is actually a macro, you cannot call
  276. it directly (all of the standard library routines have names like "sl_printf"
  277. and the macro issues a call to the appropriate routine).  These macros have
  278. two main purposes-- first, the differentiate calls to the standard library
  279. routines (i.e., no "call" instruction is the difference); and second, they
  280. contain some extra code to perform "smart linking" with MASM 5.1 & earlier,
  281. TASM, and OPTASM.  MASM 6.0 supports a new directive, extrndef, which
  282. eliminates the need for this extra code, but the extra code works nonetheless.
  283. There is a special include file, STDLIB.A6, for MASM 6.0 users which is
  284. smaller and, therefore, speeds up assemblies and consumes less memory
  285. during assembly.
  286.  
  287. All of the standard library routines, and most of their local data values,
  288. are in a segment named "stdlib".  You should not create such a segment unless
  289. you plan on adding new routines to the standard library.
  290.  
  291.  
  292. HOW THE STANDARD LIBRARY IS ORGANIZED:
  293. **************************************
  294.  
  295. In the next several pages are the documentation spec sheets for each of the
  296. standard library routines.  The routines are listed by category.  The listing
  297. of the categories and their order in the documentation is below.
  298.  
  299.     Standard Input Routines
  300.     Standard Output Routines
  301.     Conversion Routines
  302.     Utility Routines
  303.     String Handling Routines
  304.     Memory Management Routines
  305.     Character Set Routines
  306.     Floating Point Routines
  307.     File I/O
  308.     Miscellaneous Routines
  309.     SmartArray Package
  310.  
  311. In addition, at the beginning of each of the category is a brief
  312. discussion of the purpose of its routines.
  313.  
  314.  
  315.  
  316.  
  317.  
  318. Standard Input Routines:
  319. Character Input Routines
  320. ------------------------
  321.  
  322.  
  323.     The character input routines take input from either a standard
  324. device (keyboard, etc.) or a standard library.  After the character input
  325. routines receive the characters they either place the characters on the stack
  326. and/or return.  The character input routines work similar to the "C" character
  327. input routines.
  328.  
  329.  
  330.  
  331. Routine:  Getc
  332. --------------
  333.  
  334.  
  335. Category:             Character Input Routine
  336.  
  337.  
  338. Registers on Entry:   None
  339.  
  340.  
  341. Registers on Return:  AL- Character from input device.
  342.                       AH- 0 if eof, 1 if not eof.
  343.  
  344.  
  345. Flags Affected:       Carry- 0 if no error, 1 if error.  If error occurs, AX
  346.                              contains DOS error code.
  347.  
  348.  
  349. Example of Usage:  
  350.                       getc
  351.                       mov     KbdChar, al
  352.                       putc
  353.  
  354.  
  355. Description:  This routine reads a character from the standard input device.
  356.               This call is synchronous, that is, it does not return until a
  357.               character is available.  The Default input device is DOS
  358.               standard input.
  359.  
  360.               Getc returns two types of values: extended ASCII (codes 1-255)
  361.               and IBM keyboard scan codes.  If Getc returns a non-zero value,
  362.               you may interpret this value as an ASCII character.  If Getc
  363.               returns zero, you must call Getc again to get the actual
  364.               keypress.
  365.  
  366.               The second call returns an IBM PC keyboard scan code.
  367.  
  368.               Since the user may redirect input from the DOS command line,
  369.               there is the possibility of encountering end-of-file (eof)
  370.               when calling getc.  Getc uses the AH register to return eof
  371.               status.  AH contains the number of characters actually read
  372.               from the standard input device.  If it returns one, then
  373.               you've got a valid character.  If it returns zero, you've
  374.               reached end of file.  Note that pressing control-z forces an
  375.               end of file condition when reading data from the keyboard.
  376.  
  377.               This routine returns the carry flag clear if the operation
  378.               was successful.  It returns the carry flag set if some sort
  379.               of error occurred while reading the character.  Note that eof
  380.               is not an error condition.  Upon reaching the end of file,
  381.               Getc returns with the carry flag clear.  If getc is seen from
  382.               a file the control-z is not seen as an end-of-file marker,
  383.               but just read in as a character of the file.
  384.  
  385.               Control-c if read from a keyboard device aborts the program.
  386.               However if when reading something other than a keyboard
  387.               (files, serial ports), control-c from the input source
  388.               returns control-c.  However when pressing control-break
  389.               the program will abort regardless of the input source.
  390.  
  391.               Regarding CR/LF, if the input is from a device, (eg. keyboard
  392.               serial port) getc returns whatever that device driver returns,
  393.               (generally CR without a LF).  However if the input is from
  394.               a file, getc stripes a single LF if it immediately follows
  395.               the CR.
  396.  
  397.               When using getc files operate in "cooked" mode.  While
  398.               devices operate in "pseudo-cooked" mode, which means no
  399.               buffering, no CR -> CR/LF, but it handles control-c, and
  400.               control-z.
  401.  
  402.           See the sources for more information about GETC's internal
  403.           operation.
  404.  
  405. Include:    stdlib.a   
  406.  
  407.  
  408.  
  409.  
  410. Routine:   GetcStdIn
  411. --------------------
  412.  
  413.  
  414. Category:             Character Input Routine
  415.  
  416. Register on entry:    None.
  417.  
  418. Register on return:   AL- Character from input device.
  419.  
  420. Flags affected:       AH- 0 if eof, 1 if not eof.
  421.                       Carry- 0 if no error, 1 if error
  422.                       (AX contains DOS error code if error occurs).
  423.  
  424.  
  425. Example of Usage:   
  426.                       GetcStdIn
  427.                       mov     InputChr, al
  428.                       putc
  429.  
  430.  
  431. Description:    This routine reads a character from the DOS standard input
  432.                 device.  This call is synchronous, that is, it does not return
  433.                 until a character is available.  See the description of Getc
  434.                 above for more details.
  435.  
  436.         The difference between Getc and GetcStdIn is that your
  437.         program can redirect Getc using other calls in this library.
  438.         GetcStdIn calls DOS directly without going through this
  439.         redirection mechanism.
  440.  
  441.  
  442. Include:        stdlib.a
  443.  
  444.  
  445.  
  446.  
  447.  
  448.  
  449. Routine:   GetcBIOS
  450. -------------------
  451.  
  452.  
  453. Category:             Character Input Routine
  454.  
  455. Register on entry:    None
  456.  
  457. Register on return:   AL- Character from the keyboard.
  458.  
  459. Flags affected:       AH- 1 (always).  Carry- 0 (always).
  460.  
  461. Example of Usage:   
  462.                       GetcBIOS
  463.                       mov     CharRead, al
  464.                       putc
  465.  
  466.  
  467. Description:   This routine reads a character from the keyboard.  This call is
  468.                synchronous, that is it does not return until a character is
  469.                available.
  470.  
  471.         Note that there is no special character processing.  This
  472.         code does *not* check for EOF, control-C, or anything
  473.         else like that.
  474.  
  475.  
  476.  
  477. Include:        stdlib.a
  478.  
  479.  
  480.  
  481. Routine:  SetInAdrs
  482. -------------------
  483.  
  484. Category:               Character Input Routine
  485.  
  486. Registers on Entry:     ES:DI - address of new input routine
  487.  
  488. Registers on return:    None 
  489.  
  490. Flags affected:
  491.  
  492. Examples of Usage:
  493.  
  494.                         mov     es, seg NewInputRoutine
  495.                         mov     di, offset NewInputRoutine
  496.                         SetInAdrs
  497.  
  498.  
  499.  
  500.                         les     di, RoutinePtr
  501.                         SetInAdrs
  502.  
  503.  
  504. Description:    This routine redirects the stdlib standard input so that it 
  505.                 calls the routine who's address you pass in es:di.  The
  506.         routine (whose address appears in es:di) should be a "getc"
  507.         routine which reads a character from somewhere and returns
  508.         that character in AL.  It should also return EOF status in
  509.         the AH register and error status in the carry flag (see
  510.         the description of GETC for more details).
  511.  
  512.  
  513. Include:                stdlib.a
  514.  
  515.  
  516.  
  517.  
  518.  
  519. Routine:   GetInAdrs
  520. --------------------
  521.  
  522. Category:             Character Input Routine
  523.  
  524. Register on entry:    None
  525.  
  526. Register on return:   ES:DI - address of current input routine (called by Getc).
  527.  
  528. Flags affected:       None
  529.  
  530.  
  531. Example of Usage:   
  532.                       GetInAdrs
  533.                       mov     word ptr SaveInAdrs, di
  534.                       mov     word ptr SaveInAdrs+2, es
  535.  
  536.  
  537. Description:   You can use this function to get the address of the current
  538.                input routine, perhaps so you can save it or see if it is
  539.                currently pointing at some particular piece of code.
  540.                If you want to temporarily redirect the input and then restore
  541.                the original input or outline, consider using
  542.                PushInAdrs/PopInAdrs described later.
  543.  
  544.  
  545. Include:        stdlib.a
  546.  
  547.  
  548.  
  549. Routine:   PushInAdrs
  550. ---------------------
  551.  
  552. Category:             Character Input Routine
  553.  
  554. Register on entry:    ES:DI - Address of new input routine.
  555.  
  556. Register on return:   Carry=0 if operation successful.
  557.                       Carry=1 if there were already 16 items on the stack.
  558.                          
  559. Example of Usage:   
  560.                       mov     es, seg NewInputRoutine
  561.                       mov     di, offset NewInputRoutine
  562.                       PushInAdrs
  563.                         .
  564.                         .
  565.                         .
  566.                       les     di, RoutinePtr
  567.                       PushInAdrs
  568.  
  569.  
  570. Description:   This routine "pushes" the current input address onto an
  571.                internal stack and then copies the value in es:di into the
  572.                current input routine pointer.  The PushInAdrs and PopInAdrs
  573.                routines let you easily save and redirect the standard output
  574.                and then restore the original output routine address later on.
  575.                If you attempt to push more than 16 items on the stack,
  576.                PushInAdrs will ignore your request and return with the
  577.                carry flag set.  If PushInAdrs is successful, it will
  578.                return with the carry flag clear.
  579.  
  580.  
  581. Include:    stdlib.a
  582.  
  583.  
  584.  
  585.  
  586.  
  587. Routine:   PopInAdrs
  588. --------------------
  589.  
  590. Category:             Character Input Routine
  591.  
  592. Register on entry:    None
  593.  
  594. Register on return:   ES:DI - Points at the previous stdout routine before
  595.                       the pop.
  596.  
  597. Example of Usage:   
  598.                       mov     es, seg NewInRoutine
  599.                       mov     di, offset NewInputRoutine
  600.                       PushInAdrs
  601.                         .
  602.                         .
  603.                         .
  604.                       PopInAdrs
  605.  
  606.  
  607. Description:   PopInAdrs undoes the effects of PushInAdrs.  It pops an item
  608.                off the internal stack and stores it into the input routine
  609.                pointer.  The previous value in the output pointer is returned
  610.                in es:di.
  611.  
  612. Include:    stdlib.a
  613.  
  614.  
  615.  
  616.  
  617.  
  618. Routine:  Gets, Getsm
  619. ---------------------
  620.  
  621. Category:             Character Input Routine
  622.  
  623. Register on entry:    ES:DI- Pointer to input buffer (gets only).
  624.  
  625. Register on return:   ES:DI - address of input of text.
  626.                       carry-  0 if no error, 1 if error.
  627.                       If error, AX contains: 0- End of
  628.                       file encountered in middle of
  629.                       string.  1- Memory allocation error (getsm only).
  630.                       Other- DOS error code.
  631.  
  632.  
  633. Flags affected:       None
  634.  
  635. Example of usage:    
  636.                       getsm           ;Read a string from the
  637.                                       ;keyboard
  638.                       puts            ;Print it
  639.                       putcr           ;Print a new line
  640.                       free            ;Deallocate storage for
  641.                                       ;string.
  642.  
  643.               mov    di, seg buffer
  644.               mov    es, di
  645.               lea    di, buffer
  646.               gets
  647.               puts
  648.               putcr
  649.  
  650.  
  651. Description:       Reads a line of text from the stdlib standard input device.
  652.         You must pass a pointer to the recipient buffer in es:di to
  653.         the GETS routine.  GETSM automatically allocates storage for
  654.         the string on the heap (up to 256 bytes) and returns a pointer
  655.         to this block in es:di.
  656.  
  657.         Gets(m) returns all characters typed by the user except for the
  658.         carriage return (ENTER) key code.  These routines return a
  659.         zero-terminated string (with es:di pointing at the string).
  660.         Exactly how Gets(m) treats the incoming data depends upon
  661.         the source device, however, you can usually count on Gets(m)
  662.         properly handling backspace (erases previous character),
  663.         escape (erase entire line), and ENTER (accept current line).
  664.  
  665.         Other keys may affect Gets(m) as well.  For example, Gets(m),
  666.         by default, calls Getc which, in turn, usually calls DOS'
  667.         standard input routine.  If you type control-C or break while
  668.         read from DOS' standard input it may abort the program.
  669.  
  670.         If an error occurs during input (e.g., EOF encountered in
  671.         the middle of a line) Gets(m) returns the error code in
  672.         AX.  If no error occurs, Gets(m) preserves AX.
  673.  
  674. Include:                  stdlib.a
  675.  
  676.  
  677.  
  678.  
  679.  
  680. Routine:  Scanf
  681. ---------------
  682.  
  683. Category:             Character Input Routine
  684.  
  685. Register on entry:    None
  686.  
  687. Register on return:   None
  688.  
  689. Flags affected:       None
  690.  
  691. Example of usage:   
  692.                       scanf
  693.                       db      "%i  %h  %^s",0
  694.                       dd      i, x, sptr
  695.  
  696. Description:   * Formatted input from stdlib standard input.
  697.                * Similar to C's scanf routine.
  698.                * Converts ASCII to integer, unsigned, character, string, hex,
  699.                  and long values of the above.
  700.                Scanf provides formatted input in a fashion analogous to
  701.                printf's output facilities.  Actually, it turns out that scanf
  702.                is considerably less useful than printf because it doesn't
  703.                provide reasonable error checking facilities (neither does C's
  704.                version of this routine).  But for quick and dirty programs 
  705.                whose input can be controlled in a rigid fashion (or if you're
  706.                willing to live by "garbage in, garbage out")  scanf provides 
  707.                a convenient way to get input from the user.  Like printf, the
  708.                scanf routine expects you to follow the call with a format 
  709.                string and then a list of (far pointer) memory addresses.  The
  710.                items in the scanf format string take the following form: %^f,
  711.                where f represents d, i, x, h, u, c, x, ld, li, lx, or lu.  
  712.                Like printf, the "^" symbol tells scanf that the address
  713.                following the format string is the address of a (far) pointer
  714.                to the data rather than the address of the data location itself.
  715.                By default, scanf automatically skips any leading whitespace 
  716.                before attempting to read a numeric value.  You can instruct
  717.                scanf to skip other characters by placing that character in the
  718.                format string.  For example, the following call instructs scanf
  719.                to read three integers separated by commas (and/or whitespace):
  720.  
  721.                                  scanf  
  722.                   db                "%i,%i,%i",0
  723.                               dd                 i1,i2,i3
  724.  
  725.                Whenever scanf encounters a non-blank character in the format
  726.                string, it will skip that character (including multiple
  727.                occurrences of that character) if it appears next in the input
  728.                stream.  Scanf always calls gets to read a new line of text 
  729.                from stdlib's standard input.  If scanf exhausts the format 
  730.                list, it ignores any remaining characters on the line.  If
  731.                scanf exhausts the input line before processing all of the
  732.                format items, it leaves the remaining variables unchanged.
  733.                Scanf always deallocates the storage allocated by gets.
  734.  
  735.  
  736. Include:                stdlib.a
  737.  
  738.  
  739.  
  740.  
  741. Character Output Routines
  742. -------------------------
  743.  
  744.  
  745. The stdlib character output routines allow you to print to the 
  746. standard output device.  Although the processing of non-ASCII 
  747. characters is undefined, most output devices handle these characters
  748. properly.  In particular, they can handle return, line feed, back space, 
  749. and tab.  
  750.  
  751. Most of the output routines in the standard library output data 
  752. through the Putc routine.  They generally use the AX register upon 
  753. entry and print the character(s) to the standard output device by
  754. calling DOS by default. The  output is redirectable to the 
  755. user-written routine.  However, the PutcBIOS routine prints doesn't 
  756. use DOS.  Instead it uses BIOS routines to print the character in AL 
  757. using the INT command for teletype-like output. 
  758.  
  759. The print routines are similar to those in C, however, they differ
  760. in their implementation. The print routine returns to the address
  761. immediately following the terminating byte, therefore, it is important
  762. to remember to terminate your string with zero or you will print an 
  763. unexpected sequence of characters.
  764.  
  765.  
  766.  
  767. Routine:  Putc
  768. --------------
  769.  
  770. Category:             Character Output Routine
  771.  
  772. Registers on Entry:   AL- character to output
  773.  
  774. Registers on Return:  None
  775.  
  776. Flags affected:       None
  777.  
  778. Example of Usage:
  779.                        mov     al, 'C'
  780.                        putc                    ;Prints "C" to std output.
  781.  
  782.  
  783. Description:  Putc is the primitive character output routine.  Most other
  784.               output routines in the standard library output data through
  785.               this procedure.  It prints the ASCII character in AL register.  
  786.               The processing of control codes is undefined although most output
  787.               routines this routine links to should be able to handle return, 
  788.               line feed, back space, and tab.  By default, this routine calls
  789.               DOS to print the character to the standard output device.  The
  790.               output is redirectable to to user-written routine.
  791.  
  792.  
  793. Include:                stdlib.a
  794.  
  795.  
  796.  
  797. Routine:  PutCR
  798. ---------------
  799.  
  800. Category:             Character Output Routine 
  801.  
  802. Register on entry:    None
  803.  
  804. Register on return:   None
  805.  
  806. Flags affected:       None
  807.  
  808. Example of Usage:     PutCR
  809.  
  810.  
  811. Description:  Using PutCR is an easy way of printing a newline to the stdlib 
  812.               standard output. It prints a newline (carriage return/line feed) 
  813.               to the current standard output device.
  814.  
  815.  
  816. Include:                stdlib.a
  817.  
  818.  
  819. Routine: PutcStdOut
  820. -------------------
  821.  
  822. Category:              Character Output Routine
  823.  
  824. Registers on Entry:    AL- character to output
  825.  
  826. Registers on Return:   None
  827.  
  828. Flags Affected:        None
  829.  
  830. Example of Usage:
  831.                        mov AL, 'C'
  832.                        PutcStdOut        ; Writes "C" to standard output
  833.  
  834.  
  835. Description:  PutcStdOut calls DOS to print the character in AL to the standard
  836.               output device.  Although processing of non-ASCII characters and
  837.               control characters is undefined, most output devices handle these
  838.               characters properly.  In particular, most output devices properly
  839.               handle return, line feed, back space, and tab.  The output is
  840.               redirectable via DOS I/O redirection.
  841.  
  842.  
  843. Include:                stdlib.a
  844.  
  845.  
  846.  
  847. Routine: PutcBIOS
  848. -----------------
  849.  
  850. Category:              Character Output Routine
  851.  
  852. Registers on Entry:    AL- character to print
  853.  
  854. Registers on Return:   None
  855.  
  856. Flags Affected:        None
  857.  
  858. Example of Usage:
  859.                        mov AL, "C"
  860.                        PutcBIOS
  861.  
  862.  
  863. Description:  PutcBIOS prints the character in AL using the BIOS routines,
  864.               using INT 10H/AH=14 for teletype-like output.  Output through
  865.               this routine cannot be redirected; such output is always sent
  866.               to the video display on the PC (unless, of course, someone has
  867.               patched INT 10h).  Handles return, line feed, back space, and
  868.               tab.  Prints other control characters using the IBM Character
  869.           set.
  870.  
  871.  
  872. Include:         stdlib.a
  873.  
  874.  
  875.  
  876. Routine: GetOutAdrs
  877. -------------------
  878.  
  879. Category:             Character Output Routine
  880.  
  881. Registers on Entry:   None
  882.  
  883. Registers on Return:  ES:DI- address of current output routine (called by Putc)
  884.  
  885. Flags Affected:       None
  886.  
  887. Example of Usage: 
  888.                       GetOutAdrs
  889.                       mov word ptr SaveOutAdrs, DI
  890.                       mov word ptr SaveOutAdrs+2, ES
  891.  
  892. Description:  GetOutAdrs gets the address of the current output routine, perhaps
  893.               so you can save it or see if it is currently pointing at some
  894.               particular piece of code.  If you want to temporarily redirect
  895.               the output and then restore the original output routine, consider
  896.               using PushOutAdrs/PopOutAdrs described later.
  897.  
  898. Include:    stdlib.a
  899.  
  900.  
  901.  
  902.  
  903. Routine:  SetOutAdrs
  904. --------------------
  905.  
  906. Category:               Character Output Routine
  907.  
  908. Registers on Entry:     ES:DI - address of new output routine
  909.  
  910. Registers on return:    None 
  911.  
  912. Flags affected:         None
  913.  
  914. Example of Usage:
  915.  
  916.                         mov     es, seg NewOutputRoutine
  917.                         mov     di, offset NewOutputRoutine
  918.                         SetOutAdrs
  919.                         les     di, RoutinePtr
  920.                         SetOutAdrs
  921.  
  922. Description:  This routine redirects the stdlib standard output so that it
  923.               calls the routine who's address you pass in es:di.  This routine
  924.               expects the character to be in AL and must preserve all registers.
  925.               It handles the printable ASCII characters and the four control
  926.               characters return, line feed, back space, and tab.  (The routine
  927.               may be modified in the case that you wish to handle these codes
  928.               in a different fashion.)
  929.  
  930.  
  931. Include:        stdlib.a
  932.  
  933.  
  934. Routine:  PushOutAdrs
  935. ---------------------
  936.  
  937. Category:              Character Output Routine 
  938.  
  939. Registers on Entry:    ES:DI- Address of new output routine
  940.  
  941. Registers on Return:   None
  942.  
  943. Flags Affected:        Carry = 0 if operation is successful
  944.                        Carry = 1 if there were already 16 items on the stack
  945.  
  946. Example of Usage:  
  947.                        mov  ES, seg NewOutputRoutine
  948.                        mov  DI, offset NewOutputRoutine
  949.                        PushOutAdrs
  950.                           .
  951.                           .
  952.                           . 
  953.                        les  DI, RoutinePtr
  954.                        PushOutAdrs
  955.  
  956.  
  957. Description:  This routine "pushes" the current output address onto an internal
  958.               stack and then uses the value in es:di as the current output
  959.               routine address.  The PushOutAdrs and PopOutAdrs routines let you
  960.               easily save and redirect the standard output and then restore the
  961.               original output routine address later on.  If you attempt to push
  962.               more than 16 items on the stack, PushOutAdrs will ignore your
  963.               request and return with the carry flag set.  If PushOutAdrs is
  964.               successful, it will return with the carry flag clear.
  965.  
  966.  
  967. Include:          stdlib.a
  968.  
  969.  
  970.  
  971. Routine:  PopOutAdrs
  972. --------------------
  973.  
  974. Category:             Character Output Routine 
  975.  
  976. Registers on Entry:   None
  977.  
  978. Registers on Return:  ES:DI- Points at the previous stdout routine before
  979.                       the pop
  980.  
  981. Flags Affected:       None
  982.  
  983. Example of Usage:  
  984.                       mov ES, seg NewOutputRoutine
  985.                       mov DI, offset NewOutputRoutine
  986.                       PushOutAdrs
  987.                          .
  988.                          .
  989.                          .
  990.                       PopOutAdrs
  991.  
  992.  
  993. Description:  PopOutAdrs undoes the effects of PushOutAdrs.  It pops an item off
  994.               the internal stack and stores it into the output routine pointer.
  995.               The previous value in the output pointer is returned in es:di.
  996.               Defaults to PutcStdOut if you attempt to pop too many items off
  997.               the stack.
  998.  
  999. Include:    stdlib.a
  1000.  
  1001.  
  1002.  
  1003.  
  1004. Routine:  Puts
  1005. --------------
  1006.  
  1007. Category:            Character Output Routine 
  1008.  
  1009. Register on entry:   ES:DI register - contains the address of the string
  1010.  
  1011. Register on return:  None
  1012.  
  1013. Flags affected:      None
  1014.  
  1015. Example of Usage:
  1016.                      les     di, StrToPrt
  1017.                      puts
  1018.                      putcr
  1019.  
  1020.  
  1021. Description:   Puts prints a zero-terminated string whose address appears
  1022.                in es:di.  Each character appearing in the string is printed
  1023.                verbatim.  There are no special escape characters.  Unlike
  1024.                the "C" routine by the same name, puts does not print a
  1025.                newline after printing the string.  Use putcr if you want
  1026.                to print the newline after printing a string with puts.
  1027.  
  1028.  
  1029. Include:        stdlib.a
  1030.  
  1031.  
  1032.  
  1033. Routine:  Puth
  1034. --------------
  1035.  
  1036. Category:             Character Output Routine
  1037.  
  1038. Register on entry:    AL 
  1039.  
  1040. Register on return:   AL
  1041.  
  1042. Flags affected:       None
  1043.  
  1044. Example of Usage:
  1045.                       mov     al, 1fh
  1046.                       puth
  1047.  
  1048.  
  1049. Description:    The Puth routine Prints the value in the AL register as two
  1050.                 hexadecimal digits.  If the value in AL is between 0 and 0Fh, 
  1051.                 puth will print a leading zero.  This routine calls the stdlib
  1052.                 standard output routine (putc) to print all characters.
  1053.  
  1054.  
  1055. Include:        stdlib.a 
  1056.  
  1057.  
  1058.  
  1059. Routine:  Putw
  1060. --------------
  1061.  
  1062. Category:             Character Output Routine
  1063.  
  1064. Registers on Entry:   AX- Value to print
  1065.  
  1066. Registers on Return:  None
  1067.  
  1068. Flags Affected:       None
  1069.  
  1070. Example of Usage: 
  1071.                       mov AX, 0f1fh
  1072.                       putw
  1073.  
  1074.  
  1075. Description:  The Putw routine prints the value in the AX register as four
  1076.               hexadecimal digits (including leading zeros if necessary).  
  1077.               This routine calls the stdlib standard output routine (putc) 
  1078.               to print all characters.
  1079.  
  1080. Include:        stdlib.a
  1081.  
  1082.  
  1083.  
  1084. Routine:  Puti
  1085. --------------
  1086.  
  1087. Category:             Character Output Routine
  1088.  
  1089. Registers on Entry:   AX- Value to print
  1090.  
  1091. Registers on Return:  None
  1092.  
  1093. Flags Affected:       None
  1094.  
  1095. Example of Usage: 
  1096.                       mov AX, -1234
  1097.                       puti
  1098.  
  1099.  
  1100. Description:  Puti prints the value in the AX register as a decimal integer.
  1101.               This routine uses the exact number of screen positions required
  1102.               to print the number (including a position for the minus sign, if
  1103.               the number is negative).  This routine calls the stdlib standard
  1104.               output routine (putc) to print all characters.
  1105.  
  1106.  
  1107. Include:        stdlib.a
  1108.  
  1109.  
  1110.  
  1111. Routine:  Putu
  1112. --------------
  1113.  
  1114. Category:             Character Output Routine
  1115.  
  1116. Register on entry:    AX- Unsigned value to print.
  1117.  
  1118. Register on return:   None
  1119.  
  1120. Flags affected:       None
  1121.  
  1122. Example of Usage:
  1123.                       mov     ax, 1234
  1124.                       putu
  1125.  
  1126.  
  1127. Description:  Putu prints the value in the AX register as an unsigned integer.
  1128.               This routine uses the exact number of screen positions required
  1129.               to print the number.  This routine calls the stdlib standard
  1130.               output routine (putc) to print all characters.
  1131.  
  1132.  
  1133. Include:        stdlib.a
  1134.  
  1135.  
  1136.  
  1137.  
  1138. Routine:  Putl
  1139. --------------
  1140.  
  1141. Category:            Character Output Routine
  1142.  
  1143. Register on entry:   DX:AX- Value to print
  1144.  
  1145. Register on return:  None
  1146.  
  1147. Flags affected:      None
  1148.  
  1149. Example of Usage:
  1150.                      mov     dx, 0ffffh
  1151.                      mov     ax, -1234
  1152.                      putl
  1153.  
  1154.  
  1155. Description:   Putl prints the value in the DX:AX registers as an integer.
  1156.                This routine uses the exact number of screen positions
  1157.                required to print the number (including a position for the
  1158.                minus sign, if the number is negative).  This routine calls
  1159.                the stdlib standard output routine (putc) to print all
  1160.                characters.
  1161.  
  1162.  
  1163. Include:        stdlib.a
  1164.  
  1165.  
  1166.  
  1167. Routine:  Putul
  1168. ---------------
  1169.  
  1170. Category:             Character Output Routine
  1171.  
  1172. Register on entry:    DX:AX register
  1173.  
  1174. Register on return:   None
  1175.  
  1176. Flags affected:       None
  1177.  
  1178. Example of Usage:
  1179.                       mov     dx, 12h
  1180.                       mov     ax, 1234
  1181.                       putul
  1182.  
  1183.  
  1184. Description:    Putul prints the value in the DX:AX registers as an unsigned
  1185.                 integer.  This routine uses the exact number of screen
  1186.                 positions required to print the number.  This routine calls 
  1187.         the stdlib standard output routine (putc) to print all
  1188.         characters.
  1189.  
  1190.  
  1191. Include:        stdlib.a
  1192.  
  1193.  
  1194. Routine:  PutISize
  1195. ------------------
  1196.  
  1197. Category:              Character Output Routine
  1198.  
  1199. Registers on Entry:    AX - Integer value to print
  1200.                        CX - Minimum number of print positions to use
  1201.  
  1202. Registers on return:   None 
  1203.  
  1204. Flags affected:
  1205.  
  1206. Example of Usage:
  1207.                        mov     cx, 5
  1208.                        mov     ax, I
  1209.                        PutISize
  1210.                            .
  1211.                            . 
  1212.                            .
  1213.                        mov     cx, 12
  1214.                        mov     ax, J
  1215.                        PutISize
  1216.  
  1217.  
  1218. Description:    PutISize prints the signed integer value in AX to the
  1219.                 stdlib standard output device using a minimum of n print
  1220.                 positions.  CX contains n, the minimum field width for the
  1221.                 output value.  The number (including any necessary minus sign)
  1222.                 is printed right justified in the output field.
  1223.                 If the number in AX requires more print positions than
  1224.                 specified by CX, PutISize uses however many print positions
  1225.                 are necessary to actually print the number.  If you specify
  1226.                 zero in CX, PutISize uses the minimum number of print positions
  1227.                 required.  Of course, PutI will also use the minimum number
  1228.                 of print positions without disturbing the value in the CX
  1229.                 register.
  1230.  
  1231.                 Note that, under no circumstances, will the number in AX
  1232.                 ever require more than 6 print positions (-32,767 requires
  1233.                 the most print positions).
  1234.  
  1235.  
  1236. Include:        stdlib.a
  1237.  
  1238.  
  1239.  
  1240. Routine:  PutUSize
  1241. ------------------
  1242.  
  1243. Category:              Character Output Routine
  1244.  
  1245. Registers on entry:    AX- Value to print
  1246.                CX- Minimum field width
  1247.  
  1248. Registers on return:   None
  1249.  
  1250. Flags affected:        None
  1251.  
  1252. Example of usage: 
  1253.                        mov     cx, 8
  1254.                        mov     ax, U
  1255.                        PutUSize
  1256.  
  1257.  
  1258. Description:  PutUSize prints the value in AX as an unsigned decimal integer.
  1259.               The minimum field width specified by the value in CX.
  1260.               Like PutISize above except this one prints unsigned values.  
  1261.               Note that the maximum number of print positions required by any 
  1262.               number (e.g., 65,535) is five.
  1263.  
  1264.  
  1265. Include:        stdlib.a
  1266.  
  1267.  
  1268.  
  1269. Routine:  PutLSize
  1270. ------------------
  1271.  
  1272. Category:            Character Output Routine
  1273.  
  1274. Register on entry:   DX:AX-32 bit value to print
  1275.              CX- Minimum field width
  1276.  
  1277. Register on return:  None
  1278.  
  1279. Flags affected:      None
  1280.  
  1281. Example of Usage:
  1282.                      mov     cx, 16
  1283.                      mov     dx, word ptr L+2
  1284.                      mov     ax, word ptr L
  1285.                      PutLSize
  1286.  
  1287.  
  1288. Description:   PutLSize is similar to PutISize, except this prints the long 
  1289.                integer value in DX:AX.  Note that there may be as many as 
  1290.                11 print positions (e.g., -1,000,000,000).
  1291.  
  1292. Include:        stdlib.a
  1293.  
  1294.  
  1295.  
  1296.  
  1297. Routine:  PutULSize
  1298. -------------------
  1299.  
  1300.  
  1301. Category:            Character Output Routine
  1302.  
  1303.  
  1304. Register on entry:   AX : DX and CX
  1305.  
  1306.  
  1307. Register on return:  None
  1308.  
  1309.  
  1310. Flags affected:      None
  1311.  
  1312.  
  1313. Example of usage:    mov     cx, 8
  1314.                      mov     dx, word ptr UL+2
  1315.                      mov     ax, word ptr UL
  1316.                      PutULSize
  1317.  
  1318.  
  1319. Description:  Prints the value in DX:AX as a long unsigned decimal integer.
  1320.               Prints the number in a minimum field width specified by the
  1321.               value in CX.  Just like PutLSize above except this one prints
  1322.               unsigned numbers rather than signed long integers.  The largest
  1323.               field width for such a value is 10 print positions.
  1324.  
  1325.  
  1326. Include:        stdlib.a
  1327.  
  1328.  
  1329. Routine:   Print
  1330. ----------------
  1331.  
  1332. Category:             Character Output Routine
  1333.  
  1334. Register on entry:    CS:RET - Return address points at the string to print.
  1335.  
  1336. Register on return:   None
  1337.  
  1338. Flags affected:       None
  1339.  
  1340. Examples of Usage:    print
  1341.                       db      "Print this string to the display device"
  1342.                       db      13,10
  1343.                       db      "This appears on a new line"
  1344.                       db      13,10
  1345.                       db      0
  1346.  
  1347.  
  1348. Description:   Print lets you print string literals in a convenient
  1349.                fashion.  The string to print immediately follows the call
  1350.                to the print routine.  The string must contain a
  1351.                zero terminating byte and may not contain any intervening
  1352.                zero bytes.  Since the print routine returns to the address
  1353.                immediately following the zero terminating byte, forgetting
  1354.                this byte or attempting to print a zero byte in the middle
  1355.                of a literal string will cause print to return to an
  1356.                unexpected instruction.  This usually hangs up the machine.
  1357.                Be very careful when using this routine!
  1358.  
  1359.  
  1360. Include:        stdlib.a
  1361.  
  1362.  
  1363. Routine:        Printf
  1364. ----------------------
  1365.  
  1366. Category:             Character Output Routine
  1367.  
  1368. Register on entry:    CS:RET - Return address points at the format string
  1369.  
  1370. Register on return:   None
  1371.  
  1372. Flags affected:       None
  1373.  
  1374. Example of Usage:
  1375.                       printf
  1376.                       db      "Indirect access to i: %^d",13,10,0
  1377.                       dd      IPtr;
  1378.                       printf
  1379.                       db      "A string allocated on the heap: %-\.32^s"
  1380.                       db      13,10,0
  1381.                       dd      SPtr
  1382.  
  1383.  
  1384.  
  1385. Descriptions:   Printf, like its "C" namesake, provides formatted output
  1386.                 capabilities for the stdlib package.  A typical call to printf
  1387.                 always takes the following form:
  1388.  
  1389.                         printf
  1390.                         db              "format string",0
  1391.                         dd              operand1, operand2, ..., operandn
  1392.  
  1393.                 The format string is comparable to the one provided in the
  1394.                 "C" programming language.  For most characters, printf simply
  1395.                 prints the characters in the format string up to the
  1396.                 terminating zero byte.  The two exceptions are characters
  1397.                 prefixed by a backslash ("\") and characters prefixed by a
  1398.                 percent sign ("%").  Like C's printf, stdlib's printf uses
  1399.                 the backslash as an escape character and the percent sign as
  1400.                 a lead-in to a format string.
  1401.  
  1402.                 Printf uses the escape character ("\") to print special
  1403.                 characters in a fashion similar to, but not identical to C's
  1404.                 printf.  Stdlib's printf routine supports the following
  1405.                 special characters:
  1406.  
  1407.                 *  r     Print a carriage return (but no line feed)
  1408.                 *  n     Print a new line character (carriage return/line feed).
  1409.                 *  b     Print a backspace character.
  1410.                 *  t     Print a tab character.
  1411.                 *  l     Print a line feed character (but no carriage return).
  1412.                 *  f     Print a form feed character.
  1413.                 *  \     Print the backslash character.
  1414.                 *  %     Print the percent sign character.
  1415.                 *  0xhh  Print ASCII code hh, represented by two hex digits.
  1416.  
  1417.                 C users should note a couple of differences between stdlib's
  1418.                 escape sequences and C's.  First, use "\%" to print a percent
  1419.                 sign within a format string, not "%%".  C doesn't allow the
  1420.                 use of "\%" because the C compiler processes "\%" at compile
  1421.                 time (leaving a single "%" in the object code) whereas printf
  1422.                 processes the format string at run-time.  It would see a single
  1423.                 "%" and treat it as a format lead-in character.  Stdlib's
  1424.                 printf, on the other hand, processes both the "\" and "%" and
  1425.                 run-time, therefore it can distinguish "\%".
  1426.  
  1427.                 Strings of the form "\0xhh" must contain exactly two hex
  1428.                 digits.  The current printf routine isn't robust enough to
  1429.                 handle sequences of the form "\0xh" which contain only a
  1430.                 single hex digit.  Keep this in mind if you find printf
  1431.                 chopping off characters after you print a value.
  1432.  
  1433.                 There is absolutely no reason to use any escape character
  1434.                 sequences except "\0x00".  Printf grabs all characters
  1435.                 following the call to printf up to the terminating zero byte
  1436.                 (which is why you'd need to use "\0x00" if you want to print
  1437.                 the null character, printf will not print such values).
  1438.                 Stdlib's printf routine doesn't care how those characters got
  1439.                 there.  In particular, you are not limited to using a single
  1440.                 string after the printf call.  The following is perfectly
  1441.         legal:
  1442.  
  1443.  
  1444.                 printf
  1445.                 db      "This is a string",13,10
  1446.                 db      "This is on a new line",13,10
  1447.                 db      "Print a backspace at the end of this line:"
  1448.                 db      8,13,10,0
  1449.  
  1450.  
  1451.                 Your code will run a tiny amount faster if you avoid the use
  1452.                 of the escape character sequences.  More importantly, the
  1453.                 escape character sequences take at least two bytes.  You can
  1454.                 encode most of them as a single byte by simply embedding the
  1455.                 ASCII code for that byte directly into the code stream.
  1456.                 Don't forget, you cannot embed a zero byte into the code
  1457.                 stream.  A zero byte terminates the format string.  Instead,
  1458.                 use the "\0x00" escape sequence.
  1459.  
  1460.                 Format sequences always between with "%".  For each format
  1461.                 sequence you must provide a far pointer to the associated
  1462.                 data immediately following the format string, e.g.,
  1463.  
  1464.                     printf
  1465.                     db      "%i %i",0
  1466.                     dd      i,j
  1467.  
  1468.                 Format sequences take the general form "%s\cn^f" where:
  1469.  
  1470.                 *       "%" is always the "%" character.  Use "\%" if you
  1471.                         actually want to print a percent sign.
  1472.                 *       s is either nothing or a minus sign ("-").
  1473.                 *       "\c" is also optional, it may or may not appear in
  1474.                         the format item.  "c" represents any printable
  1475.                         character.
  1476.                 *       "n" represents a string of 1 or more decimal digits.
  1477.                 *       "^" is just the caret (up-arrow) character.
  1478.                 *       "f" represents one of the format characters: i, d, x,
  1479.                         h, u, c, s, ld, li, lx, or lu.
  1480.  
  1481.                 The "s", "\c", "n", and "^" items are optional, the "%" and
  1482.                 "f" items must be present.  Furthermore, the order of these
  1483.                 items in the format item is very important.  The "\c" entry,
  1484.                 for example, cannot precede the "s" entry.  Likewise, the "^"
  1485.                 character, if present, must follow everything except the "f"
  1486.                 character(s).
  1487.  
  1488.                 The format characters i, d, x, h, u, c, s, ld, li, lx, and
  1489.                 lu control the output format for the data.  The i and d
  1490.                 format characters perform identical functions, they tell
  1491.                 printf to print the following value as a 16-bit signed
  1492.                 decimal integer.  The x and h format characters instruct
  1493.                 printf to print the specified value as a 16-bit or 8-bit
  1494.                 hexadecimal value (respectively).  If you specify u, printf
  1495.                 prints the value as a 16-bit unsigned decimal integer.
  1496.                 Using c tells printf to print the value as a single character.
  1497.                 S tells printf that you're supplying the address of a
  1498.                 zero-terminated character string, printf prints that string.
  1499.                 The ld, li, lx, and lu entries are long (32-bit) versions of
  1500.                 d/i, x, and u.  The corresponding address points at a 32-bit
  1501.                 value which printf will format and print to the standard output.
  1502.                 The following example demonstrates these format items:
  1503.  
  1504.                 printf
  1505.                 db      "I= %i, U= %u, HexC= %h, HexI= %x, C= %c, "
  1506.                 db      "S= %s",13,10
  1507.                 db      "L= %ld",13,10,0
  1508.                 dd      i,u,c,i,c,s,l
  1509.  
  1510.                 The number of far addresses (specified by operands to the "dd"
  1511.                 pseudo-opcode) must match the number of "%" format items in
  1512.                 the format string.  Printf counts the number of "%" format
  1513.                 items in the format string and skips over this many far
  1514.                 addresses following the format string.  If the number of
  1515.                 items do not match, the return address for printf will be
  1516.                 incorrect and the program will probably hang or otherwise
  1517.                 malfunction.  Likewise (as for the print routine), the format
  1518.                 string must end with a zero byte.  The addresses of the items
  1519.                 following the format string must point directly at the memory
  1520.                 locations where the specified data lies.
  1521.  
  1522.                 When used in the format above, printf always prints the
  1523.                 values using the minimum number of print positions for each
  1524.                 operand.  If you want to specify a minimum field width, you
  1525.                 can do so using the "n" format option.  A format item of the
  1526.                 format "%10d" prints a decimal integer using at least ten
  1527.                 print positions.  Likewise, "%16s" prints a string using at
  1528.                 least 16 print positions.  If the value to print requires
  1529.                 more than the specified number of print positions, printf
  1530.                 will use however many are necessary.  If the value to print
  1531.                 requires fewer, printf will always print the specified number,
  1532.                 padding the value with blanks.  Printf will print the value
  1533.                 right justified in the print field (regardless of the data's
  1534.                 type).  If you want to print the value left justified in the
  1535.                 output file, use the "-" format character as a prefix to the
  1536.                 field width, e.g.,
  1537.  
  1538.                 printf
  1539.                 db      "%-17s",0
  1540.                 dd      string
  1541.  
  1542.                 In this example, printf prints the string using a 17 character
  1543.                 long field with the string left justified in the output field.
  1544.                 By default, printf blank fills the output field if the value
  1545.                 to print requires fewer print positions than specified by the
  1546.                 format item.  The "\c" format item allows you to change the
  1547.                 padding character.  For example, to print a value, right
  1548.                 justified, using "*" as the padding character you would use
  1549.                 the format item "%\*10d".  To print it left justified you
  1550.                 would use the format item "%-\*10d".  Note that the "-" must
  1551.                 precede the "\*".  This is a limitation of the current
  1552.                 version of the software.  The operands must appear in this
  1553.                 order.  Normally, the address(es) following the printf
  1554.                 format string must be far pointers to the actual data to print.
  1555.                 On occasion, especially when allocating storage on the heap
  1556.                 (using malloc), you may not know (at assembly time) the
  1557.                 address of the object you want to print.  You may have only
  1558.                 a pointer to the data you want to print.  The "^" format
  1559.                 option tells printf that the far pointer following the format
  1560.                 string is the address of a pointer to the data rather than
  1561.                 the address of the data itself.  This option lets you access
  1562.                 the data indirectly.
  1563.  
  1564.                 Note: unlike C, stdlib's printf routine does not support
  1565.                 floating point output.  Putting floating point into printf
  1566.         would increase the size of this routine a tremendous amount.
  1567.         Since most people don't need the floating point output
  1568.         facilities, it doesn't appear here.  Check out PRINTFF.
  1569.  
  1570. Include:        stdlib.a
  1571.  
  1572.  
  1573.  
  1574. Routine:  PRINTFF
  1575. -----------------
  1576.  
  1577.  
  1578. Category:             Character Output Routine
  1579.  
  1580. Registers on Entry:   CS:RET- Points at format string and other parameters.
  1581.  
  1582. Registers on Return:  If your program prints floating point values, this
  1583.               routine modifies the floating point accumulator and
  1584.               floating point operand "pseudo-registers" in the
  1585.               floating point package.
  1586.  
  1587. Flags Affected:       None
  1588.  
  1589. Examples of Usage:
  1590.             printff
  1591.             db    "I = %d, R = %7.2f  F = 12.5e  G = 9.2gf\n",0
  1592.             dd    i, r, f, g
  1593.  
  1594. Description:  
  1595.         This code works just like printf except it also allows the
  1596.         output of floating point values.  The output formats are 
  1597.         the following:
  1598.  
  1599.         Single Precision:
  1600.  
  1601.          mm.nnF-    Prints a field width of mm chars with nn digits
  1602.                 appearing after the decimal point.
  1603.  
  1604.          nnE-        Prints a floating point value using scientific
  1605.                 notation in a field width of nn chars.
  1606.  
  1607.         Double Precision:
  1608.  
  1609.          mm.nnGF-    As above, for double precision values.
  1610.          nnGE-        As above, for double precision values.
  1611.  
  1612.         Extended Precision-
  1613.  
  1614.          mm.nnLF-    As above, for extended precision values.
  1615.          nnLE-        As above, for extended precision values.
  1616.  
  1617.  
  1618.         Since PRINTFF supports everything PRINTF does, you should not
  1619.         use both routines in the same program (just use PRINTF).  The
  1620.         PRINTF & PRINTFF macros check for this and will print a warning
  1621.         message if you've included both routines.  Using both will not
  1622.         cause your program to fail, but it will make your program
  1623.         unnecessarily larger.  You should not use PRINTFF unless you
  1624.         really need to print floating point values.  When you use
  1625.         PRINTFF, it forces the linker to load in the entire floating
  1626.         point package, making your program considerably larger.
  1627.  
  1628. Include:                  stdlib.a
  1629.  
  1630.  
  1631.  
  1632. Conversion Routines
  1633. -------------------
  1634.  
  1635.  
  1636. The stdlib conversion routines follow a uniform format of storing the data
  1637. to be converted and returned.  Most routines accept input and return data
  1638. of either an ASCII string of characters, stored in the ES:DI register, or
  1639. integers, stored in the DX:AX register.  If a value is just a 16 or 8-bit
  1640. value then it will be stored in AX or AL.
  1641.  
  1642. Since there is a possibility of an error in the input values to be converted,
  1643. such as it does not contain a proper value to convert, we use the
  1644. carry flag to show error status.  If the error flag is set then an error has
  1645. occured and things are okay if the carry flag is clear.
  1646.  
  1647.  
  1648.  
  1649.  
  1650.  
  1651. Routine:  ATOL (2)
  1652. ------------------
  1653.  
  1654.  
  1655. Category:             Conversion Routine
  1656.  
  1657. Registers on Entry:   ES:DI- Points at string to convert
  1658.  
  1659. Registers on Return:  DX:AX- Long integer converted from string
  1660.               ES:DI- Points at first non-digit (ATOL2 only)
  1661.  
  1662. Flags Affected:       Carry flag- Error status
  1663.  
  1664. Examples of Usage:
  1665.               gets         ;Get a string from user
  1666.               ATOL         ;Convert to a value in DX:AX
  1667.  
  1668.  
  1669. Description:  ATOL converts the string of digits that ES:DI points at to a
  1670.           long (signed) integer value and returns this value in DX:AX.
  1671.           Note that the routine stops on the first non-digit.
  1672.           If the string does not begin with a digit, this routine returns
  1673.           zero.  The only exception to the "string of digits" only rule is
  1674.           that the number can have a preceding minus sign to denote a
  1675.           negative number.  Note that this routine does not allow leading
  1676.           spaces.  ATOL2 works in a similar fashion except it doesn't
  1677.           preserve the DI register.  That is, ATOL2 leaves DI pointing at
  1678.           the first character beyond the string of digits.  ATOL/ATOL2 both
  1679.           return the carry flag clear if it  translated the string of
  1680.           digits without error.  It returns the carry flag set if overflow
  1681.           occurred.
  1682.  
  1683.  
  1684. Include:                  stdlib.a
  1685.  
  1686.  
  1687.  
  1688. Routine:  AtoUL (2)
  1689. -------------------
  1690.  
  1691. Category:            Conversion Routine
  1692.  
  1693. Register on entry:   ES:DI- address of the string to be converted
  1694.  
  1695. Register on return:  DX:AX- 32-bit unsigned integer
  1696.              ES:DI- Points at first character beyond digits (ATOUL2
  1697.                 only)
  1698.  
  1699. Flags affected:      Carry flag- Set if error, clear if okay.
  1700.  
  1701. Examples of Usage:
  1702.              les InputString
  1703.              AtoUL
  1704.  
  1705.  
  1706. Description:  AtoUL converts the string pointed by ES:DI to a 32-bit unsigned
  1707.           integer.  It places the 32-bit unsigned integer into the memory
  1708.           address pointed by DX:AX. If there is an error in conversion,
  1709.           the carry flag will set to one. If there is not an error, the
  1710.           carry flag will be set to zero.
  1711.  
  1712.           ATOUL2 does not preserve DI.  It returns with DI pointing at
  1713.           the first non-digit character in the string.
  1714.  
  1715. Include:        stdlib.a
  1716.  
  1717.  
  1718.  
  1719. Routine:    ATOU (2)
  1720. --------------------
  1721.  
  1722. Category:            Conversion Routine
  1723.  
  1724. Register on entry:   ES:DI points at string to convert
  1725.  
  1726. Register on return:  AX-    unsigned 16-bit integer
  1727.              ES:DI- points at first non-digit (ATOU2 only)
  1728.  
  1729. Flags affected:      carry flag - error status
  1730.  
  1731. Example of Usage:
  1732.  
  1733. Description:    ATOU converts an ASCII string of digits, pointed to by ES:DI,
  1734.         to unsigned integer format. It places the unsigned 16-bit
  1735.         integer, converted from the string, into the AX register.
  1736.         ATOI works the same, except it handle unsigned 16-bit integers
  1737.         in the range 0..65535.
  1738.  
  1739.         ATOU2 leaves DI pointing at the first non-digit in the string.
  1740.  
  1741. Include:        stdlib.a
  1742.  
  1743.  
  1744.  
  1745. Routine: ATOH (2)
  1746. -----------------
  1747.  
  1748. Category:             Conversion Routine
  1749.  
  1750. Registers on Entry:   ES:DI- Points to string to convert
  1751.  
  1752. Registers on Return:  AX- Unsigned 16-bit integer converted from hex string
  1753.               DI (ATOH2)- First character beyond string of hex digits
  1754.  
  1755. Flags Affected:       Carry = Error status
  1756.  
  1757. Example of Usage:
  1758.               les  DI, Str2Convrt
  1759.               atoh                  ;Convert to value in AX.
  1760.               putw                  ;Print word in AX.
  1761.  
  1762.  
  1763. Description:  ATOH converts a string of hexadecimal digits, pointed to by
  1764.           ES:DI, into unsigned 16-bit numeric form. It returns the value in
  1765.           the AX register.  If there is an error in conversion, the carry
  1766.           flag will set to one.  If there is not an error, the carry flag
  1767.           will be clear.  ATOH2 works the same except it leaves DI
  1768.           pointing at the first character beyond the string of hex digits.
  1769.  
  1770. Include:        stdlib.a
  1771.  
  1772.  
  1773. Routine: ATOLH (2)
  1774. ------------------
  1775.  
  1776. Category:             Conversion Routine
  1777.  
  1778. Registers on Entry:   ES:DI- Points to string to convert
  1779.  
  1780. Registers on Return:  DX:AX- Unsigned 32-bit integer converted from hex string
  1781.               DI (ATOLH2)- First character beyond string of hex digits
  1782.  
  1783. Flags Affected:       Carry = Error status
  1784.  
  1785. Example of Usage:
  1786.               les  DI, Str2Convrt
  1787.               atolh                 ;Convert to value in DX:AX
  1788.  
  1789. Description:  ATOLH converts a string of hexadecimal digits, pointed to by
  1790.           ES:DI, into unsigned 32-bit numeric form. It returns the value in
  1791.           the DX:AX register.  If there is an error in conversion, the carry
  1792.           flag will set to one.  If there is not an error, the carry flag
  1793.           will be clear.  ATOLH2 works the same except it leaves the DI
  1794.           register pointing at the first non-hex digit.
  1795.  
  1796.  
  1797. Include:        stdlib.a
  1798.  
  1799.  
  1800.  
  1801. Routine:   ATOI (2)
  1802. -------------------
  1803.  
  1804. Category:             Conversion Routine
  1805.  
  1806. Register on entry:    ES:DI- Points at string to convert.
  1807.  
  1808. Register on return:   AX- Integer converted from string.
  1809.               DI (ATOI2)- First character beyond string of digits.
  1810.  
  1811. Flags affected:       Error status
  1812.  
  1813. Examples of Usage:
  1814.               les  DI, Str2Convrt
  1815.               atoi                 ;Convert to value in AX
  1816.  
  1817.  
  1818. Description:   Works just like ATOL except it translates the string to a
  1819.            signed 16-bit integer rather than a 32-bit long integer.
  1820.  
  1821.  
  1822. Include:              stdlib.a
  1823.  
  1824.  
  1825. Routine ITOA (2,M)
  1826. ------------------
  1827.  
  1828. Category:             Conversion Routine
  1829.  
  1830. Registers on Entry:   AX- Signed 16-bit value to convert to a string
  1831.               ES:DI- Pointer to buffer to hold result (ITOA/ITOA2
  1832.                  only).
  1833.  
  1834. Registers on Return:  ES:DI- Pointer to string containing converted
  1835.               characters (ITOA/ITOAM only).
  1836.               ES:DI- Pointer to zero-terminating byte of converted
  1837.                  string (ITOA2 only).
  1838.  
  1839. Flags Affected:       Carry flag is set on memory allocation error (ITOAM only)
  1840.  
  1841. Examples of Usage:
  1842.               mov     ax, -1234
  1843.               ITOAM                   ;Convert to string.
  1844.               puts                    ;Print it.
  1845.               free                    ;Deallocate string.
  1846.  
  1847.               mov     di, seg buffer
  1848.               mov     es, di
  1849.               lea     di, buffer
  1850.               mov     ax, -1234
  1851.               ITOA              ;Leaves string in BUFFER.
  1852.  
  1853.               mov     di, seg buffer
  1854.               mov     es, di
  1855.               lea     di, buffer
  1856.               mov     ax, -1234
  1857.               ITOA2              ;Leaves string in BUFFER and
  1858.                           ;ES:DI pointing at end of string.
  1859.  
  1860.  
  1861. Description:    These routines convert an integer value to a string of
  1862.         characters which represent that integer.  AX contains the
  1863.         signed integer you wish to convert.
  1864.  
  1865.         ITOAM automatically allocates storage on the heap for the
  1866.         resulting string, you do not have to pre-allocate this
  1867.         storage.  ITOAM returns a pointer to the (zero-terminated)
  1868.         string in the ES:DI registers.  It ignores the values in
  1869.         ES:DI on input.
  1870.  
  1871.         ITOA requires that the caller allocate the storage for the
  1872.         string (maximum you will need is seven bytes) and pass a
  1873.         pointer to this buffer in ES:DI.  ITOA returns with ES:DI
  1874.         pointing at the beginning of the converted string.
  1875.  
  1876.         ITOA2 also requires that you pass in the address of a buffer
  1877.         in the ES:DI register pair.  However, it returns with ES:DI
  1878.         pointing at the zero-terminating byte of the string.  This
  1879.         lets you easily build up longer strings via multiple calls
  1880.         to routines like ITOA2.
  1881.  
  1882. Include:        stdlib.a
  1883.  
  1884.  
  1885.  
  1886. Routine:   UTOA (2,M)
  1887. ---------------------
  1888.  
  1889. Category:            Conversion Routine
  1890.  
  1891. Registers on entry:   AX - unsigned 16-bit integer to convert to a string
  1892.               ES:DI- Pointer to buffer to hold result (UTOA/UTOA2
  1893.                  only).
  1894.  
  1895. Registers on Return:  ES:DI- Pointer to string containing converted
  1896.               characters (UTOA/UTOAM only).
  1897.               ES:DI- Pointer to zero-terminating byte of converted
  1898.                  string (UTOA2 only).
  1899.  
  1900. Flags affected:       Carry set denotes malloc error (UTOAM only)
  1901.  
  1902. Example of Usage:
  1903.               mov     ax, 65000
  1904.               utoa
  1905.               puts
  1906.               free
  1907.  
  1908.               mov     di, seg buffer
  1909.               mov     es, di
  1910.               lea     di, buffer
  1911.               mov     ax, -1234
  1912.               ITOA              ;Leaves string in BUFFER.
  1913.  
  1914.               mov     di, seg buffer
  1915.               mov     es, di
  1916.               lea     di, buffer
  1917.               mov     ax, -1234
  1918.               ITOA2              ;Leaves string in BUFFER and
  1919.                           ;ES:DI pointing at end of string.
  1920.  
  1921.  
  1922. Description:    UTOAx converts a 16-bit unsigned integer value in AX to a
  1923.         string of characters which represents that value.  UTOA,
  1924.         UTOA2, and UTOAM behave in a manner analogous to ITOAx.  See
  1925.         the description of those routines for more details.
  1926.  
  1927.  
  1928. Include:       stdlib.a
  1929.  
  1930.  
  1931.  
  1932. Routine:   HTOA (2,M)
  1933. ---------------------
  1934.  
  1935. Category:            Conversion Routine
  1936.  
  1937. Registers on entry:   AL - 8-bit integer to convert to a string
  1938.               ES:DI- Pointer to buffer to hold result (HTOA/HTOA2
  1939.                  only).
  1940.  
  1941. Registers on Return:  ES:DI- Pointer to string containing converted
  1942.               characters (HTOA/HTOAM only).
  1943.               ES:DI- Pointer to zero-terminating byte of converted
  1944.                  string (HTOA2 only).
  1945.  
  1946. Flags affected:      Carry set denotes memory allocation error (HTOAM only)
  1947.  
  1948.  
  1949. Description:    The HTOAx routines convert an 8-bit value in AL to the two-
  1950.         character hexadecimal representation of that byte.  Other
  1951.         that that, they behave just like ITOAx/UTOAx.  Note that
  1952.         the resulting buffer must have at least three bytes for
  1953.         HTOA/HTOA2.
  1954.  
  1955.  
  1956. Include:        stdlib.a
  1957.  
  1958.  
  1959. Routine:  WTOA (2,M)
  1960. --------------------
  1961.  
  1962. Category:             Conversion Routine
  1963.  
  1964. Registers on Entry:   AX- 16-bit value to convert to a string
  1965.               ES:DI- Pointer to buffer to hold result (WTOA/WTOA2
  1966.                  only).
  1967.  
  1968. Registers on Return:  ES:DI- Pointer to string containing converted
  1969.               characters (WTOA/WTOAM only).
  1970.               ES:DI- Pointer to zero-terminating byte of converted
  1971.                  string (WTOA2 only).
  1972.  
  1973. Flags Affected:       Carry set denotes memory allocation error (WTOAM only)
  1974.  
  1975. Example of Usage:
  1976.               Like WTOA above
  1977.  
  1978.  
  1979. Description:  WTOAx converts the 16-bit value in AX to a string of four
  1980.           hexadecimal digits. It behaves exactly like HTOAx except
  1981.           it outputs four characters (and requires a five byte buffer).
  1982.  
  1983.  
  1984. Include:        stdlib.a
  1985.  
  1986.  
  1987.  
  1988. Routine:  LTOA (2,M)
  1989. --------------------
  1990.  
  1991. Category:             Conversion Routine
  1992.  
  1993. Registers on entry:   DX:AX (contains a signed 32 bit integer)
  1994.               ES:DI- Pointer to buffer to hold result (LTOA/LTOA2
  1995.                  only).
  1996.  
  1997. Registers on Return:  ES:DI- Pointer to string containing converted
  1998.               characters (LTOA/LTOAM only).
  1999.               ES:DI- Pointer to zero-terminating byte of converted
  2000.                  string (LTOA2 only).
  2001.  
  2002. Flags affected:       Carry set if memory allocation error (LTOAM only)
  2003.  
  2004.  
  2005. Example of Usage: 
  2006.             mov    di, seg buffer    ;Get address of storage
  2007.             mov    es, di        ; buffer.
  2008.             lea    di, buffer
  2009.             mov    ax, word ptr value
  2010.             mov    dx, word ptr value+2
  2011.             ltoa
  2012.  
  2013. Description:    LtoA converts the 32-bit signed integer in DX:AX to a string
  2014.         of characters.  LTOA stores the string at the address specified
  2015.         in ES:DI (there must be at least twelve bytes available at
  2016.         this address) and returns with ES:DI pointing at this buffer.
  2017.         LTOA2 works the same way, except it returns with ES:DI
  2018.         pointing at the zero terminating byte.  LTOAM allocates
  2019.         storage for the string on the heap and returns a pointer
  2020.         to the string in ES:DI.
  2021.  
  2022. Include:        stdlib.a
  2023.  
  2024.  
  2025.  
  2026. Routine:  ULTOA (2,M)
  2027. ---------------------
  2028.  
  2029. Category:             Conversion Routine
  2030.  
  2031. Registers on Entry:   DX:AX- Unsigned 32-bit value to convert to a string
  2032.               ES:DI- Pointer to buffer to hold result (LTOA/LTOA2
  2033.                  only).
  2034. Registers on Return:  ES:DI- Pointer to string containing converted
  2035.               characters (LTOA/LTOAM only).
  2036.               ES:DI- Pointer to zero-terminating byte of converted
  2037.                  string (LTOA2 only).
  2038.  
  2039. Flags Affected:       Carry is set if malloc error (ULTOAM only)
  2040.  
  2041. Example of Usage:  
  2042.                       Like LTOA
  2043.  
  2044.  
  2045. Description:  Like LTOA except this routine handles unsigned integer values.
  2046.  
  2047. Include:    stdlib.a
  2048.  
  2049.  
  2050.  
  2051. Routine:  SPrintf (2,M)
  2052. -----------------------
  2053.  
  2054. Category:            Conversion Routine
  2055.              In-Memory Formatting Routine
  2056.  
  2057. Registers on entry:  CS:RET - Pointer to format string and operands of the
  2058.                   sprintf routine
  2059.              ES:DI-   Address of buffer to hold output string
  2060.                   (sprintf/sprintf2 only)
  2061.  
  2062. Register on return:  ES:DI register - pointer to a string containing
  2063.                       output data (sprintf/sprintfm only).
  2064.                       Pointer to zero-terminating byte at the
  2065.                       end of the converted string (sprintf2
  2066.                       only).
  2067.  
  2068. Flags affected:      Carry is set if memory allocation error (sprintfm only).
  2069.  
  2070. Example of Usage:
  2071.              sprintfm
  2072.              db      "I=%i, U=%u, S=%s",13,10,0
  2073.              db      i,u,s
  2074.              puts
  2075.              free
  2076.  
  2077.  
  2078. Description:   SPrintf is an in-memory formatting routine. It is similar to
  2079.            C's sprintf routine.
  2080.  
  2081.            The programmer selects the maximum length of the output string.
  2082.            SPrintf works in a manner quite similar to printf, except sprintf
  2083.            writes its output to a string variable rather than to the stdlib
  2084.            standard output.
  2085.  
  2086.            SPrintfm, by default, allocates 2048 characters for the string
  2087.            and then deallocates any unnecessary storage.  An external
  2088.            variable, sp_MaxBuf, holds the number of bytes to allocate upon
  2089.            entry into sprintfm.  If you wish to allocate more or less than
  2090.            2048 bytes when calling sprintf, simply change the value of this
  2091.            public variable (type is word).  Sprintfm calls malloc to
  2092.            allocate the storage dynamically.  You should call free to
  2093.            return this buffer to the heap when you are through with it.
  2094.  
  2095.            Sprintf and Sprintf2 expect you to pass the address of a buffer
  2096.            to them.  You are responsible for supplying a sufficiently
  2097.            sized buffer to hold the result.
  2098.  
  2099. Include:             stdlib.a
  2100.  
  2101.  
  2102.  
  2103. Routine:  SScanf
  2104. ----------------
  2105.  
  2106. Category:              Conversion Routine
  2107.                Formatted In-Memory Conversion Routine
  2108.  
  2109. Registers on Entry:    ES:DI - points at string containing values to convert
  2110.  
  2111. Registers on return:   None
  2112.  
  2113. Flags affected:           None
  2114.  
  2115. Example of Usage:
  2116.  
  2117.           ; this code reads the values for i, j, and s from the characters
  2118.           ; starting at memory location Buffer.
  2119.  
  2120.                les   di, Buffer
  2121.                SScanf
  2122.                db    "%i %i %s",0
  2123.                dd     i, j, s
  2124.  
  2125.  
  2126. Description:  SScanf provides formatted input in a fashion analogous to scanf.
  2127.               The difference is that scanf reads in a line of text from the
  2128.               stdlib standard input whereas you pass the address of a sequence
  2129.               of characters to SScanf in es:di.
  2130.  
  2131.  
  2132. Include:                stdlib.a
  2133.  
  2134.  
  2135.  
  2136.  
  2137. Routine:  ToLower
  2138. -----------------
  2139.  
  2140. Category:            Conversion Routine
  2141.  
  2142. Register on entry:   AL- Character to (possibly) convert
  2143.                 to lower case.
  2144.  
  2145. Register on return:  AL- Converted character.
  2146.  
  2147. Flags affected:      None
  2148.  
  2149. Example of usage:
  2150.              mov     al, char
  2151.              ToLower
  2152.  
  2153.  
  2154. Description:  ToLower checks the character in the AL register, if it is upper
  2155.           case it converts it to lower case.  If it is anything else,
  2156.           ToLower leaves the value in AL unchanged.  For high performance
  2157.           this routine is implemented as a macro rather than as a
  2158.           procedure call.  This routine is so short you would spend more
  2159.           time actually calling the routine than executing the code inside.
  2160.           However, the code is definitely longer than a (far) procedure
  2161.           call, so if space is critical and you're invoking this code
  2162.           several times, you may want to convert it to a procedure call to
  2163.           save a little space.
  2164.  
  2165.  
  2166. Include:             stdlib.a
  2167.  
  2168.  
  2169.  
  2170. Routine:   ToUpper
  2171. ------------------
  2172.  
  2173. Category:             Conversion Routine
  2174.  
  2175. Registers on Entry:   AL- Character to (possibly) convert to upper case
  2176.  
  2177. Registers on Return:  AL- Converted character
  2178.  
  2179. Flags Affected:       None
  2180.  
  2181. Example of Usage:
  2182.               mov  al, char
  2183.               ToUpper
  2184.  
  2185.  
  2186. Description:  ToUpper checks the character in the AL register, if it is lower
  2187.           case it converts it to upper case.  If it is anything else,
  2188.           ToUpper leaves the value in AL unchanged.  For high performance
  2189.           this routine is implemented as a macro rather than as a
  2190.           procedure call (see ToLower, above).
  2191.  
  2192.  
  2193. Include:              stdlib.a
  2194.  
  2195.  
  2196.  
  2197.  
  2198.  
  2199. Utility Routines
  2200. ----------------
  2201.  
  2202. The following routines are all Utility Routines.  The first routines listed
  2203. below compute the number of print positions required by a 16-bit and 32-bit
  2204. signed and unsigned integer value.  UlSize is like the LSize except it treats
  2205. the value in DX:AX as an unsigned long integer.  The next set of routines in
  2206. this section check the character in the AL register to see whether it is a
  2207. hexidecimal digit, if it alphabetic, if it is a lower case alphabetic, if it
  2208. is a upper case alphabetic, and if it is numeric.  Then there are some
  2209. miscellaneous routines (macros) which process command line parameters, invoke
  2210. DOS and exit the program.
  2211.  
  2212.  
  2213.  
  2214. Routine:  ISize
  2215. ---------------
  2216.  
  2217. Category:            Utility Routine
  2218.  
  2219. Register on entry:   AX- 16-bit value to compute the
  2220.                 output size for.
  2221.  
  2222. Register on return:  AX- Number of print positions
  2223.                 required by this number (including
  2224.                 the minus sign, if necessary).
  2225.  
  2226. Flags affected:      None
  2227.  
  2228. Example of usage:
  2229.              mov     ax, I
  2230.              ISize
  2231.              puti                    ;Prints positions
  2232.                          ;req'd by I.
  2233.  
  2234.  
  2235. Description:         This routine computes the number of print positions
  2236.              required by a 16-bit signed integer value.  ISize computes
  2237.              the minimum number of character positions it takes to print
  2238.              the signed decimal value in the AX register.  If the number
  2239.              is negative, it will include space for the minus sign in
  2240.              the count.
  2241.  
  2242.  
  2243. Include:             stdlib.a
  2244.  
  2245.  
  2246.  
  2247.  
  2248. Routine:  USize
  2249. ---------------
  2250.  
  2251. Category:            Utility Routine
  2252.  
  2253. Register on entry:   AX- 16 bit value to compute the
  2254.                 output size for
  2255.  
  2256. Register on return:  AX- number of print positions
  2257.              required by this number (including
  2258.              the minus sign, if necessary)
  2259.  
  2260. Flags affected:      None
  2261.  
  2262. Example of usage:
  2263.              mov     ax, I
  2264.              USize
  2265.              puti                    ;prints position
  2266.                          ;required by I
  2267.  
  2268.  
  2269. Description:         This routine computes the number of print positions
  2270.              required by a 16-bit signed integer value.  It also
  2271.              computes the number of print positions required by a
  2272.              16-bit unsigned value.  USize computes the minimum number
  2273.              of character positions it will take to print an unsigned
  2274.              decimal value in the AX register.  If the number is
  2275.              negative, it will include space for the minus sign in the
  2276.              count.
  2277.  
  2278.  
  2279. Include:             stdlib.a
  2280.  
  2281.  
  2282. Routine:  LSize
  2283. ---------------
  2284.  
  2285. Category:            Utility Routine
  2286.  
  2287. Register on entry:   DX:AX   - 32-bit value to compute the
  2288.                    output size for.
  2289.  
  2290. Register on return:  AX - Number of print positions
  2291.               required by this number (including
  2292.               the minus sign, if necessary).
  2293.  
  2294. Flags affected:      None
  2295.  
  2296. Example of Usage:
  2297.              mov     ax, word ptr L
  2298.              mov     dx, word ptr L+2
  2299.              LSize
  2300.              puti                    ;Prints positions
  2301.                          ;req'd by L.
  2302.  
  2303.  
  2304. Description:         This routine computes the number of print positions
  2305.              required by a 32-bit signed integer value.  LSize computes
  2306.              the minimum number of character positions it will take to
  2307.              print the signed decimal value in the DX:AX registers.  If
  2308.              the number is negative, it will include space for the minus
  2309.              sign in the count.
  2310.  
  2311.  
  2312. Include:             stdlib.a
  2313.  
  2314.  
  2315.  
  2316. Routine:  ULSize
  2317. ----------------
  2318.  
  2319. Category:             Utility Routine
  2320.  
  2321. Registers on Entry:   DX:AX - 32-bit value to compute the output size for.
  2322.  
  2323. Registers on return:  AX - number of print positions required by this number
  2324.  
  2325. Flags affected:       None
  2326.  
  2327. Example of Usage:
  2328.               mov     ax, word ptr L
  2329.               mov     dx, word ptr L+2
  2330.               ULSize
  2331.               puti                    ; Prints positions req'd by L
  2332.  
  2333.  
  2334. Description:          ULSize computes the minimum number of character
  2335.               positions it will take to print an unsigned decimal
  2336.               value in the DX:AX registers.
  2337.  
  2338.  
  2339. Include:              stdlib.a
  2340.  
  2341.  
  2342.  
  2343. Routine:  IsAlNum
  2344. -----------------
  2345.  
  2346. Category:             Utility routine
  2347.  
  2348. Register on entry:    AL - character to check.
  2349.  
  2350. Register on return:   None
  2351.  
  2352. Flags affected:       Zero flag - set if character is alphanumeric,
  2353.               clear if not.
  2354.  
  2355.  
  2356. Example of usage :    mov al, char
  2357.               IsAlNum
  2358.               je IsAlNumChar
  2359.  
  2360.  
  2361. Description :         This routine checks the character in the AL register to
  2362.               see if it is in the range A-Z, a-z, or 0-9.  Upon return,
  2363.               you can use the JE instruction to check to see if the
  2364.               character was in this range (or, conversely, you can use
  2365.               JNE to see if it is not in range).
  2366.  
  2367.  
  2368. Include:              stdlib.a
  2369.  
  2370.  
  2371. Routine:  IsXDigit
  2372. ------------------
  2373.  
  2374. Category:               Utility Routine
  2375.  
  2376. Register on Entry:     AL- character to check
  2377.  
  2378. Registers on Return:    None
  2379.  
  2380. Flags Affected:         Zero flag-  Set if character is a hex digit, clear if not
  2381.  
  2382.  
  2383. Example of Usage:       mov    al, char
  2384.             IsXDigit
  2385.             je     IsXDigitChar
  2386.  
  2387.  
  2388. Description:            This routine checks the character in the AL register to
  2389.             see if it is in the range A-F, a-f, or 0-9.  Upon
  2390.             return, you can use the JE instruction to check to see
  2391.             if the character was in this range (or, conversely,
  2392.             you can use jne to see if it is not in the range).
  2393.  
  2394.  
  2395. Include:                stdlib.a
  2396.  
  2397.  
  2398. Routine:   IsDigit
  2399. ------------------
  2400.  
  2401. Category:            Utility Routine
  2402.  
  2403. Register on entry:   AL- Character to check
  2404.  
  2405. Register on return:  None
  2406.  
  2407. Flags affected:         Zero flag- set if character is numeric, clear if not.
  2408.  
  2409. Example of Usage:    mov   al, char
  2410.              IsDigit
  2411.              je  IsDecChar
  2412.  
  2413.  
  2414. Description:         This routine checks the character in the AL register to
  2415.              see if it is in the range 0-9.  Upon return, you can use
  2416.              the JE instruction to check to see if the character was
  2417.              in the range (or, conversely, you can use JNE to see if it
  2418.              is not in the range).
  2419.  
  2420.  
  2421. Include:             stdlib.a
  2422.  
  2423.  
  2424. Routine:   IsAlpha
  2425. ------------------
  2426.  
  2427. Category:            Utility Routine
  2428.  
  2429. Register on entry:   AL- Character to check
  2430.  
  2431. Register on return:  None
  2432.  
  2433. Flags affected:         Zero flag- set if character is alphabetic, clear if not.
  2434.  
  2435. Example of Usage:    mov   al, char
  2436.              IsAlpha
  2437.              je   IsAlChar
  2438.  
  2439.  
  2440. Description:         This routine checks the character in the AL register to
  2441.              see if it is in the range A-Z or a-z.  Upon return, you
  2442.              can use the JE instruction to check to see if the character
  2443.              was in the range (or, conversely, you can use JNE to see
  2444.              if it is not in the range).
  2445.  
  2446. Include:             stdlib.a
  2447.  
  2448.  
  2449.  
  2450.  
  2451. Routine: IsLower
  2452. ----------------
  2453.  
  2454. Category:             Utility Routine
  2455.  
  2456. Registers on Entry:   AL- character to test
  2457.  
  2458. Registers on Return:  None
  2459.  
  2460.  
  2461. Flags Affected:       Zero = 1 if character is a lower case alphabetic character
  2462.               Zero = 0 if character is not a lower case alphabetic
  2463.               character
  2464.  
  2465. Example of Usage:     mov  AL, char        ; put char in AL
  2466.               IsLower              ; is char lower a-z?
  2467.               je  IsLowerChar      ; if yes, jump to IsLowerChar
  2468.  
  2469.  
  2470. Description:          This routine checks the character in the AL register to
  2471.               see if it is in the range a-z.  Upon return, you can use
  2472.               the JE instruction to check and see if the character was
  2473.               in this range (or you can use JNE to check and see if
  2474.               the character was not in this range).  This procedure is
  2475.               implemented as a macro for high performance.
  2476.  
  2477.  
  2478. Include:              stdlib.a
  2479.  
  2480.  
  2481. Routine:  IsUpper
  2482. -----------------
  2483.  
  2484. Category:             Utility Routine
  2485.  
  2486. Registers on Entry:   AL- character to check
  2487.  
  2488. Registers on Return:  None
  2489.  
  2490. Flags Affected:       Zero flag - set if character is uppercase alpha, clear
  2491.                   if not.
  2492.  
  2493.  
  2494. Example of Usage:     mov al, char
  2495.               IsUpper
  2496.               je IsUpperChar
  2497.  
  2498.  
  2499. Description:          This routine checks the character in the AL register to
  2500.               see if it is in the ranger A-Z.  Upon return, you can use
  2501.               the JE instruction to check to see if it not in the
  2502.               range).  It uses macro implementation for high performance.
  2503.  
  2504.  
  2505. Include:              stdlib.a
  2506.  
  2507.  
  2508. Routine:  Argc
  2509. --------------
  2510.  
  2511. Category:             Utility Routine
  2512.  
  2513. Registers on Entry:   None
  2514.  
  2515. Registers on Return:  CX-    Number of command line parameters
  2516.  
  2517. Flags Affected:       None
  2518.  
  2519.  
  2520. Example of Usage:     
  2521.             print
  2522.             db    "There were ",0
  2523.             argc
  2524.             mov    ax, cx
  2525.             puti
  2526.             print
  2527.             db    " command line parameters here",cr,lf,0
  2528.  
  2529. Description:    This routine returns the number of command line para-
  2530.         meters on the DOS command line.  Note that strings enclosed
  2531.         in quotation marks or apostrophes are counted as a single
  2532.         command line parameter.
  2533.  
  2534.  
  2535. Include:              stdlib.a
  2536.  
  2537.  
  2538. Routine:  Argv
  2539. --------------
  2540.  
  2541. Category:             Utility Routine
  2542.  
  2543. Registers on Entry:   AX-    Which parameter to grab (1..n).
  2544.               PSP-    Global variable containing the DOS program
  2545.                 segment prefix value.
  2546.  
  2547. Registers on Return:  ES:DI-    Pointer to string on heap containing the
  2548.                 specified parameter (empty string if the
  2549.                 parameter does not exist).
  2550.  
  2551. Flags Affected:       carry-    Set if malloc error.
  2552.  
  2553.  
  2554. Example of Usage:     
  2555.             mov    ax, 2
  2556.             argv
  2557.             print
  2558.             db    "The second command line parameter is ",0
  2559.             puts
  2560.             free
  2561.  
  2562. Description:    
  2563.  This routine returns a string containing the specified command line argument.
  2564. You must pass the position number of the argument in AX; this routine returns
  2565. the specified string on the heap with ES:DI pointing at the string.  Note that
  2566. the command line parameters are numbered starting from one.  If you specify an
  2567. out of range value, this routine returns a pointer to a zero byte (the empty
  2568. string).
  2569.  
  2570.  
  2571. Include:              stdlib.a
  2572.  
  2573.  
  2574. Routine:  GetEnv
  2575. ----------------
  2576.  
  2577. Category:             Utility Routine
  2578.  
  2579. Registers on Entry:   ES:DI-    Points at a string containing the name of
  2580.                 the environment variable you want to find.
  2581.               PSP-    Global variable containing the DOS program
  2582.                 segment prefix value.
  2583.  
  2584. Registers on Return:  ES:DI-    Pointer to string in the environment space
  2585.                 containing the characters immediately after
  2586.                 the name of the environment variable in the
  2587.                 environment string space.
  2588.  
  2589. Flags Affected:       carry-    Set if malloc error.
  2590.  
  2591.  
  2592. Example of Usage:     
  2593.             les    di, EnvVarStrPtr
  2594.             getenv
  2595.             print
  2596.             db    "The value of the environment variable is ",0
  2597.             puts
  2598.             free
  2599.  
  2600. Description:    
  2601.  
  2602.   This routine returns a pointer to the first characters following an
  2603. environment variable in the program's environment variable space.  It points
  2604. at the very first character following the name, so it typically points at
  2605. an equal sign (e.g., the PATH environment variable is typically of the form
  2606. "PATH=xxxxxxxx" and the "=" is the first char past the name).  If this routine
  2607. does not find the specified environment variable, it returns a pointer to
  2608. a single zero byte.  Since the pointer is in the environment space, you should
  2609. not store anything at this address.  Instead, first copy the string with STRDUP
  2610. if you need to modify it.
  2611.  
  2612. Include:              stdlib.a
  2613.  
  2614.  
  2615. Routine:  DOS
  2616. -------------
  2617.  
  2618. Category:             Utility Routine
  2619.  
  2620. Registers on Entry:   AH-    DOS opcode
  2621.  
  2622. Registers on Return:  Depends on particular DOS call
  2623.  
  2624. Flags Affected:       Depends on DOS call.
  2625.  
  2626.  
  2627. Example of Usage:     
  2628.             mov    ah, 9
  2629.             DOS
  2630.              .
  2631.              .
  2632.              .
  2633.             DOS    7
  2634. Description:    
  2635.  
  2636.   This macro invokes DOS via the INT 21h interrupt.  If there is no parameter
  2637. to the macro, it simply issues the INT 21h instruction.  If a parameter is
  2638. present, it emits "mov ah, operand" followed by the INT 21h instruction.
  2639.  
  2640. Include:              stdlib.a
  2641.  
  2642.  
  2643. Routine:  ExitPgm
  2644. -----------------
  2645.  
  2646. Category:             Utility Routine
  2647.  
  2648. Registers on Entry:  None
  2649.  
  2650. Registers on Return:  Doesn't return
  2651.  
  2652. Flags Affected:       N/A
  2653.  
  2654.  
  2655. Example of Usage:     
  2656.             ExitPgm
  2657. Description:    
  2658.  
  2659.   This macro exits the program and returns to DOS.
  2660.  
  2661. Include:              stdlib.a
  2662.  
  2663.  
  2664.  
  2665. String Handling Routines
  2666. ------------------------
  2667.  
  2668. Manipulating text is a major part of many computer applications. Typically,
  2669. strings are inputed and interpreted. This interpretation may involve some
  2670. chores such as extracting certain part of the text, copying it, or comparing
  2671. with other strings.
  2672.  
  2673. The string manipulation routines in C provides various functions. Therefore,
  2674. the stdlib has some C-like string handling functions (e.g. strcpy, strcmp).
  2675. In C a string is an array of characters; similarly, the string are terminated
  2676. by a "0" as a null character. In general, the input strings of these routines
  2677. are pointed by ES:DI. In some routines, the carry flag will be set to indicate
  2678. an error.
  2679.  
  2680. The following string routines take as many as four different forms: strxxx,
  2681. strxxxl, strxxxm, and strxxxlm.  These routines differ in how they store
  2682. the destination string into memory and where they obtain their source strings.
  2683.  
  2684. Routines of the form strxxx generally expect a single source string address
  2685. in ES:DI or a source and destination string in ES:DI & DX:SI.  If these
  2686. routines produce a string, they generally store the result into the buffer
  2687. pointed at by ES:DI upon entry.  They return with ES:DI pointing at the
  2688. first character of the destination string.
  2689.  
  2690. Routines of the form strxxxl have a "literal source string".  A literal
  2691. source string follows the call to the routine in the code stream.  E.g.,
  2692.  
  2693.             strcatl
  2694.             db    "Add this string to ES:DI",0
  2695.  
  2696. Routines of the form strxxxm automatically allocate storage for a source
  2697. string on the heap and return a pointer to this string in ES:DI.
  2698.  
  2699. Routines of the form strxxxlm have a literal source string in the code
  2700. stream and allocate storage for the destination string on the heap.
  2701.  
  2702.  
  2703.  
  2704. Routine:  Strcpy (l)
  2705. --------------------
  2706.  
  2707. Category:             String Handling Routine
  2708.  
  2709. Registers on Entry:   ES:DI - pointer to source string (Strcpy only)
  2710.               CS:RET - pointer to  source  string (Strcpy1 only)
  2711.               DX:SI - pointer to destination string
  2712.  
  2713.  
  2714. Registers on return:  ES:DI - points at the destination string
  2715.  
  2716.  
  2717. Flags affected:          None
  2718.  
  2719.  
  2720. Example of Usage:
  2721.               mov     dx, seg Dest
  2722.               mov     si, offset Dest
  2723.               mov     di, seg Source
  2724.               mov     es, di
  2725.               mov     si, offset Source
  2726.               Strcpy
  2727.  
  2728.               mov     dx, seg Dest
  2729.               mov     si, offset Dest
  2730.               Strcpyl
  2731.               db      "String to copy",0
  2732.  
  2733.  
  2734. Description:  Strcpy is used to copy a zero-terminated string from one
  2735.           location to another.  ES:DI points at the source string,
  2736.           DX:SI points at the destination address.  Strcpy copies all
  2737.           bytes, up to and including the zero byte, from the source
  2738.           address to the destination address.  The target buffer must
  2739.           be large enough to hold the string.  Strcpy performs no error
  2740.           checking on the size of the destination buffer.
  2741.  
  2742.           Strcpyl copies the  zero-terminated string immediately following
  2743.           the call instruction to the destination address specified by
  2744.           DX:SI.  Again, this routine expects you to ensure that the
  2745.           taraget buffer is large enough to hold the result.
  2746.  
  2747.           Note: There are no "Strcpym" or "Strcpylm" routines.  The
  2748.           reason is simple: "StrDup" and "StrDupl" provide these functions
  2749.           using names which are familiar to MSC and Borland C users.
  2750.  
  2751. Include:              stdlib.a
  2752.  
  2753.  
  2754. Routine:  StrDup (l)
  2755. --------------------
  2756.  
  2757. Category:            String Handling Routine
  2758.  
  2759. Register on entry:   ES:dI - pointer to source string (StrDup
  2760.              only).  CS:RET - Pointer to source string
  2761.              (StrDupl only).
  2762.  
  2763. Register on return:  ES:DI - Points at the destination string
  2764.              allocated on heap.  Carry=0 if operation
  2765.              successful.  Carry=0 if insufficient
  2766.              memory for new string.
  2767.  
  2768. Flags affected:      Carry flag
  2769.  
  2770. Example of usage:
  2771.              StrDupl
  2772.              db "String for StrDupl",0
  2773.              jc  MallocError
  2774.              mov word ptr Dest1, di
  2775.              mov word ptr Dest1+2, es  ;create another
  2776.                            ;copy of this
  2777.                            ;string. Note
  2778.                            ;that es:di points
  2779.                            ;at Dest1 upon
  2780.                            ;entry to StrDup,
  2781.                            ;but it points at
  2782.                            ;the new string on
  2783.                            ;exit
  2784.              StrDup
  2785.              jc MallocError
  2786.              mov word ptr Dest2, di
  2787.              mov word ptr Dest2+2, es
  2788.  
  2789.  
  2790. Description:  StrDup and StrDupl duplicate strings.  You pass them
  2791.           a pointer to the string (in es:di for strdup, via
  2792.           the return address for strdupl) and they allocate
  2793.           sufficient storage on the heap for a copy of this
  2794.           string.  Then these two routines copy their source
  2795.           strings to the newly allocated storage and return
  2796.           a pointer to the new string in ES:DI.
  2797.  
  2798.  
  2799. Include:             stdlib.a
  2800.  
  2801.  
  2802. Routine:  Strlen
  2803. ----------------
  2804.  
  2805. Category:            String Handling Routine
  2806.  
  2807. Registers on entry:  ES:DI - pointer to source string.
  2808.  
  2809. Register on return:  CX - length of specified string.
  2810.  
  2811. Flags Affected:      None
  2812.  
  2813. Examples of Usage:
  2814.              les   di, String
  2815.              strlen
  2816.              mov   sl, cx
  2817.              printf
  2818.              db   "Length of '%s' is %d\n",0
  2819.              dd   String, sl
  2820.  
  2821.  
  2822. Description:  Strlen computes the length of the string whose address
  2823.           appears in ES:DI.  It returns the number of characters
  2824.           up to, but not including, the zero terminating byte.
  2825.  
  2826. Include:             stdlib.a
  2827.  
  2828.  
  2829. Routine:  Strcat (m,l,ml)
  2830. -------------------------
  2831.  
  2832. Category:             String Handling Routine
  2833.  
  2834. Registers on Entry:   ES:DI- Pointer to first string
  2835.               DX:SI- Pointer to second string (Strcat and Strcatm only)
  2836.  
  2837.  
  2838. Registers on Return:  ES:DI- Pointer to new string (Strcatm and Strcatml only)
  2839.  
  2840. Flags Affected:       Carry = 0 if no error
  2841.               Carry = 1 if insufficient memory (Strcatm and Strcatml
  2842.                             only)
  2843.  
  2844.  
  2845. Example of Usage:     les  DI, String1
  2846.               mov  DX, seg String2
  2847.               lea  SI, String2
  2848.               Strcat                   ; String1 <- String1 + String2
  2849.  
  2850.               les  DI, String1
  2851.               Strcatl                  ; String1 <- String1 +
  2852.               db  "Appended String",0  ;            "Appended String",0
  2853.  
  2854.  
  2855.               les  DI, String1
  2856.               mov  DX, seg String2
  2857.               lea  SI, String2
  2858.               Strcatm                  ; NewString <- String1 + String2
  2859.               puts
  2860.               free
  2861.  
  2862.               les  DI, String1
  2863.               Strcatml                 ; NewString <- String1 +
  2864.               db  "Appended String",0  ;         "Appended String",0
  2865.               puts
  2866.               free
  2867.  
  2868.  
  2869. Description:  These routines concatenate two strings together.  They differ
  2870.           mainly in the location of their source and destination operands.
  2871.  
  2872.           Strcat concatenates the string pointed at by DX:SI to the end of
  2873.           the string pointed at by ES:DI in memory.  Both strings must be
  2874.           zero-terminated.  The buffer pointed at by ES:DI must be large
  2875.           enough to hold the resulting string.  Strcat does NOT perform
  2876.           bounds checking on the data.
  2877.  
  2878.           ( continued on next page )
  2879.  
  2880.  
  2881.  
  2882.  
  2883.  
  2884.  
  2885.  
  2886. Routine:  Strcat (m,l,ml)   ( continued )
  2887. -----------------------------------------
  2888.  
  2889.  
  2890.           Strcatm computes the length of the two strings pointed at by ES:DI
  2891.           and DX:SI and attempts to allocate this much storage on the heap.
  2892.           If it is not successful, Strcatm returns with the Carry flag set,
  2893.           otherwise it copies the string pointed at by ES:DI to the heap,
  2894.           concatenates the string DX:SI points at to the end of this string
  2895.           on the heap, and returns with the Carry flag clear and ES:DI
  2896.           pointing at the new (concatenated) string on the heap.
  2897.  
  2898.           Strcatl and Strcatml work just like Strcat and Strcatm except you
  2899.           supply the second string as a literal constant immediately AFTER
  2900.           the call rather than pointing DX:SI at it (see examples above).
  2901.  
  2902.  
  2903. Include:             stdlib.a
  2904.  
  2905.  
  2906. Routine:  Strchr
  2907. ----------------
  2908.  
  2909. Category:            String Handling Routine
  2910.  
  2911. Register on entry:   ES:DI- Pointer to string.
  2912.             AL- Character to search for.
  2913.  
  2914. Register on return:  CX- Position (starting at zero)
  2915.              where Strchr found the character.
  2916.  
  2917. Flags affected:      Carry=0 if Strchr found the character.
  2918.              Carry=1 if the character was not present
  2919.                  in the string.
  2920.  
  2921. Example of usage:
  2922.              les di, String
  2923.              mov al, Char2Find
  2924.              Strchr
  2925.              jc  NotPresent
  2926.              mov CharPosn, cx
  2927.  
  2928.  
  2929. Description:  Strchr locates the first occurrence of a character within a
  2930.           string.  It searches through the zero-terminated string pointed
  2931.           at by es:di for the character passed in AL. If it locates the
  2932.           character, it returns the position of that character to the CX
  2933.           register.  The first character in the string corresponds to the
  2934.           location zero.  If the character is not in the string, Strchr
  2935.           returns the carry flag set.  CX's value is undefined in that
  2936.           case.  If Strchr locates the character in the string, it
  2937.           returns with the carry clear.
  2938.  
  2939.  
  2940. Include:             stdlib.a
  2941.  
  2942.  
  2943. Routine:  Strstr (l)
  2944. --------------------
  2945.  
  2946. Category:            String Handling Routine
  2947.  
  2948. Register on entry:   ES:DI - Pointer to string.
  2949.              DX:SI - Pointer to substring(strstr).
  2950.              CS:RET - Pointer to substring (strstrl).
  2951.  
  2952. Register on return:  CX - Position (starting at zero)
  2953.              where Strstr/Strstrl found the
  2954.              character.  Carry=0 if Strstr/
  2955.              Strstrl found the character.
  2956.              Carry=1 if the character was not
  2957.              present in the string.
  2958.  
  2959. Flags affected:      Carry flag
  2960.  
  2961. Example of usage :
  2962.              les di, MainString
  2963.              lea si, Substring
  2964.              mov dx, seg Substring
  2965.              Strstr
  2966.              jc NoMatch
  2967.              mov i, cx
  2968.              printf
  2969.              db "Found the substring '%s' at location %i\n",0
  2970.              dd Substring, i
  2971.  
  2972.  
  2973. Description:  Strstr searches for the position of a substring
  2974.           within another string.  ES:DI points at the
  2975.           string to search through, DX:SI points at the
  2976.           substring.  Strstr returns the index into ES:DI's
  2977.           string where DX:SI's string is found.  If the
  2978.           string is found, Strstr returns with the carry
  2979.           flag clear and CX contains the (zero based) index
  2980.           into the string.  If Strstr cannot locate the
  2981.           substring within the string ES:DI points at, it
  2982.           returns the carry flag set.  Strstrl works just
  2983.           like Strstr except it excepts the substring to
  2984.           search for immediately after the call instruction
  2985.           (rather than passing this address in DX:SI).
  2986.  
  2987.  
  2988. Include:              stdlib.a
  2989.  
  2990.  
  2991. Routine:  Strcmp (l)
  2992. --------------------
  2993.  
  2994. Category:            String Handling Routine
  2995.  
  2996. Registers on entry:  ES:DI contains the address of the first string
  2997.              DX:SI contains the address of the second string (strcmp)
  2998.              CS:RET (contains the address of the substring (strcmpl)
  2999.  
  3000. Register on return:  CX (contains the position where the two strings differ)
  3001.  
  3002. Flags affected:      Carry flag and zero flag (string1 > string2 if C + Z = 0)
  3003.                      (string1 < string2 if C = 1)
  3004.  
  3005. Example of Usage:
  3006.              les     di, String1
  3007.              mov     dx, seg String2
  3008.              lea     si, String2
  3009.              strcmp
  3010.              ja        OverThere
  3011.  
  3012.              les     di, String1
  3013.              strcmpl
  3014.              db     "Hello",0
  3015.              jbe     elsewhere
  3016.  
  3017.  
  3018.  
  3019. Description:  Strcmp compares the first strings pointed by ES:DI with
  3020.           the second string pointed by DX:SI. The carry and zero flag
  3021.           will contain the corresponding result. So unsigned branch
  3022.           instructions such as JA or JB is recommended. If string1
  3023.           equals string2, strcmp will return with CX containing the
  3024.           offset of the zero byte in the two strings.
  3025.  
  3026.           Strcmpl compares the first string pointed by ES:DI with
  3027.           the substring pointed by CS:RET. The carry and zero flag
  3028.           will contain the corresponding result. So unsigned branch
  3029.           instructions such as JA or JB are recommended. If string1
  3030.           equals to the substring, strcmp will return with CX
  3031.           containing the offset of the zero byte in the two strings.
  3032.  
  3033. Include:             stdlib.a
  3034.  
  3035.  
  3036. Routine:  Strupr (m)
  3037. --------------------
  3038.  
  3039. Category:            String Handling Routine
  3040.              Conversion Routine
  3041.  
  3042. Register on entry:   ES:DI (contains the pointer to input string)
  3043.  
  3044. Register on return:  ES:DI (contains the pointer to input string
  3045.                with characters converted to upper case)
  3046.                Note: struprm allocates storage for a new
  3047.                string on the heap and returns the pointer
  3048.                to this routine in ES:DI.
  3049.  
  3050. Flags affected:      Carry = 1 if memory allocation error (Struprm only).
  3051.  
  3052. Example of Usage:
  3053.              les     di, lwrstr1
  3054.              strupr
  3055.              puts
  3056.  
  3057.              mov        di, seg StrWLwr
  3058.              mov    es, di
  3059.              lea    di, StrWLwr
  3060.              struprm
  3061.              puts
  3062.              free
  3063.  
  3064.  
  3065. Description:  Strupr converts the input string pointed by ES:DI to
  3066.           upper case.  It will actually modify the string you pass
  3067.           to it.
  3068.  
  3069.           Struprm first makes a copy of the string on the heap and
  3070.           then converts the characters in this new string to upper
  3071.           case.  It returns a pointer to the new string in ES:DI.
  3072.  
  3073. Include:             stdlib.a
  3074.  
  3075.  
  3076. Routine:  Strlwr (m)
  3077. --------------------
  3078.  
  3079. Category:            String Handling Routine
  3080.              Conversion Routine
  3081.  
  3082. Register on entry:   ES:DI (contains the pointer to input string)
  3083.  
  3084. Register on return:  ES:DI (contains the pointer to input string
  3085.                with characters converted to lower case).
  3086.  
  3087. Flags affected:      Carry = 1 if memory allocation error (strlwrm only)
  3088.  
  3089.  
  3090. Example of Usage:
  3091.              les di, uprstr1
  3092.              strlwr
  3093.              puts
  3094.  
  3095.              mov        di, seg StrWLwr
  3096.              mov    es, di
  3097.              lea    di, StrWLwr
  3098.              strlwrm
  3099.              puts
  3100.              free
  3101.  
  3102.  
  3103.  
  3104.  
  3105. Description:  Strlwr converts the input string pointed by ES:DI to
  3106.           lower case. It will actually modify the string you pass
  3107.           to it.
  3108.  
  3109.           Strlwrm first copies the characters onto the heap and then
  3110.           returns a pointer to this string after converting all the
  3111.           alphabetic characters to lower case.
  3112.  
  3113.  
  3114. Include:             stdlib.a
  3115.  
  3116.  
  3117.  
  3118. Routine:  Strset (m)
  3119. --------------------
  3120.  
  3121. Category:            String Handling Routine
  3122.  
  3123. Register on entry:   ES:DI contains the pointer to input string (StrSet only)
  3124.              AL    contains the character to copy
  3125.              CX    contains number of characters to allocate for
  3126.                the string (Strsetm only)
  3127.  
  3128. Register on return:  ES:DI pointer to newly allocated string (Strsetm only)
  3129.  
  3130. Flags affected:      Carry set if memory allocation error (Strsetm only)
  3131.  
  3132. Example of Usage:
  3133.              les     di, string1
  3134.              mov    al, " "        ;Blank fill string.
  3135.              Strset
  3136.  
  3137.              mov     cx, 32
  3138.              mov    al, "*"        ;Create a new string w/32
  3139.              Strsetm            ; asterisks.
  3140.              puts
  3141.              free
  3142.  
  3143.  
  3144. Description:  Strset overwrites the data on input string pointed by
  3145.           ES:DI with the character on AL.
  3146.  
  3147.           Strsetm creates a new string on the heap with the number
  3148.           of characters specified in CX.  All characters in the string
  3149.           are initialized with the value in AL.
  3150.  
  3151. Include:             stdlib.a
  3152.  
  3153.  
  3154. Routine:  Strspan (l)
  3155. ---------------------
  3156.  
  3157. Category:             String Handling Routine
  3158.  
  3159. Registers on Entry:   ES:DI - Pointer to string to scan
  3160.               DX:SI - Pointer to character set (Strspan only)
  3161.               CS:RET- Pointer to character set (Strspanl only)
  3162.  
  3163. Registers on Return:  CX- First position in scanned string which does not
  3164.               contain one of the characters in the character set
  3165.  
  3166. Flags Affected:       None
  3167.  
  3168. Example of Usage:
  3169.               les  DI, String
  3170.               mov  DX, seg CharSet
  3171.               lea  SI, CharSet
  3172.               Strspan           ; find first position in String with a
  3173.               mov i, CX         ;                  char not in CharSet
  3174.               printf
  3175.               db  "The first char which is not in CharSet "
  3176.               db  "occurs at position %d in String.\n",0
  3177.               dd  i
  3178.  
  3179.               les  DI, String
  3180.               Strspanl          ; find first position in String which
  3181.               db   "aeiou",0    ; is not a vowel
  3182.               mov  j, CX
  3183.               printf
  3184.               db  "The first char which is not a vowel "
  3185.               db  "occurs at position %d in String.\n",0
  3186.               dd  j
  3187.  
  3188.  
  3189. Description:  Strspan(l) scans a string, counting the number of characters which
  3190.           are present in a second string (which represents a character set).
  3191.           ES:DI points at a zero-terminated string of characters to scan.
  3192.           DX:SI (strspan) or CS:RET (strspanl) points at another zero-
  3193.           terminated string containing the set of characters to compare
  3194.           against.  The position of the first character in the string
  3195.           pointed to by ES:DI which is NOT in the character set is returned.
  3196.           If all the characters in the string are in the character set, the
  3197.           position of the zero-terminating byte will be returned.
  3198.  
  3199.           Although strspan and (especially) strspanl are very compact and
  3200.           convenient to use, they are not particularly efficient.  The
  3201.           character set routines provide a much faster alternative at the
  3202.           expense of a little more space.
  3203.  
  3204.  
  3205. Include:               stdlib.a
  3206.  
  3207.  
  3208. Routine:  Strcspan, Strcspanl
  3209. -----------------------------
  3210.  
  3211. Category:             String Handling Routine
  3212.  
  3213. Registers on Entry:   ES:DI - Pointer to string to scan
  3214.               DX:SI - Pointer to character set (Strcspan only)
  3215.               CS:RET- Pointer to character set (Strcspanl only)
  3216.  
  3217. Registers on Return:  CX- First position in scanned string which contains one
  3218.               of the characters in the character set
  3219.  
  3220. Flags Affected:       None
  3221.  
  3222. Example of Usage:
  3223.               les  DI, String
  3224.               mov  DX, seg CharSet
  3225.               lea  SI, CharSet
  3226.               Strcspan          ; find first position in String with a
  3227.               mov i, CX         ;                      char in CharSet
  3228.               printf
  3229.               db  "The first char which is in CharSet "
  3230.               db  "occurs at position %d in String.\n",0
  3231.               dd  i
  3232.  
  3233.               les  DI, String
  3234.               Strcspanl         ; find first position in String which
  3235.               db   "aeiou",0    ; is a vowel.
  3236.               mov  j, CX
  3237.               printf
  3238.               db  "The first char which is a vowel occurs "
  3239.               db  "at position %d in String.\n",0
  3240.               dd  j
  3241.  
  3242.  
  3243. Description:  Strcspan(l) scans a string, counting the number of characters
  3244.           which are NOT present in a second string (which represents a
  3245.           character set).  ES:DI points at a zero-terminated string of
  3246.           characters to scan.  DX:SI (strcspan) or CS:RET (strcspanl) points
  3247.           at another zero-terminated string containing the set of characters
  3248.           to compare against.  The position of the first character in the
  3249.           string pointed to by ES:DI which is in the character set is
  3250.           returned.  If all the characters in the string are not in the
  3251.           character set, the position of the zero-terminating byte will be
  3252.           returned.
  3253.  
  3254.           Although strcspan and strcspanl are very compact and convenient to
  3255.           use, they are not particularly efficient.  The character set
  3256.           routines provide a much faster alternative at the expense of a
  3257.           little more space.
  3258.  
  3259. Include:              stdlib.a
  3260.  
  3261.  
  3262. Routine:  StrIns (m,l,ml)
  3263. -------------------------
  3264.  
  3265. Category:             String Handling Routine
  3266.  
  3267. Registers on Entry:   ES:DI - Pointer to destination string (to insert into)
  3268.               DX:SI - Pointer to string to insert
  3269.                       (StrIns and StrInsm only)
  3270.               CX    - Insertion point in destination string
  3271.  
  3272. Registers on Return:  ES:DI - Pointer to new string (StrInsm and StrInsml only)
  3273.  
  3274. Flags Affected:       Carry = 0 if no error
  3275.               Carry = 1 if insufficient memory
  3276.                    (StrInsm and StrInsml only)
  3277.  
  3278.  
  3279. Example of Usage:
  3280.               les  DI, DestStr
  3281.               mov  DX, word ptr SrcStr+2
  3282.               mov  SI, word ptr SrcStr
  3283.               mov  CX, 5
  3284.               StrIns     ; Insert SrcStr before the 6th char of DestStr
  3285.  
  3286.               les  DI, DestStr
  3287.               mov  CX, 2
  3288.               StrInsl    ; Insert "Hello" before the 3rd char of DestStr
  3289.               db  "Hello",0
  3290.  
  3291.               les  DI, DestStr
  3292.               mov  DX, word ptr SrcStr+2
  3293.               mov  SI, word ptr SrcStr
  3294.               mov  CX, 11
  3295.               StrInsm      ; Create a new string by inserting SrcStr
  3296.                    ;         before the 12th char of DestStr
  3297.               puts
  3298.               putcr
  3299.               free
  3300.  
  3301.  
  3302. Description:  These routines insert one string into another string.  ES:DI
  3303.           points at the string into which you want to insert another.  CX
  3304.           contains the position (or index) where you want the string
  3305.           inserted.  This index is zero-based, so if CX contains zero, the
  3306.           source string will be inserted before the first character in the
  3307.           destination string.  If CX contains a value larger than the size
  3308.           of the destination string, the source string will be appended to
  3309.           the destination string.
  3310.  
  3311.           StrIns inserts the string pointed at by DX:SI into the string
  3312.           pointed at by ES:DI at position CX.  The buffer pointed at by
  3313.           ES:DI must be large enough to hold the resulting string.  StrIns
  3314.           does NOT perform bounds checking on the data.
  3315.  
  3316.      ( continued on next page )
  3317.  
  3318.  
  3319. Routine:  StrIns (m,l,ml)   ( continued )
  3320. -----------------------------------------
  3321.  
  3322.           StrInsm does not modify the source or destination strings, but
  3323.           instead attempts to allocate a new buffer on the heap to hold the
  3324.           resulting string.  If it is not successful, StrInsm returns with
  3325.           the Carry flag set, otherwise the resulting string is created and
  3326.           its address is returned in the ES:DI registers.
  3327.  
  3328.           StrInsl and StrInsml work just like StrIns and StrInsm except you
  3329.           supply the second string as a literal constant immediately AFTER
  3330.           the call rather than pointing DX:SI at it (see examples above).
  3331.  
  3332.  
  3333.  
  3334. Routine:  StrDel, StrDelm
  3335. -------------------------
  3336.  
  3337. Category:              String Handling Routine
  3338.  
  3339. Registers on Entry:    ES:DI -  pointer to string
  3340.                CX - deletion point in  string
  3341.                AX - number of characters to delete
  3342.  
  3343. Registers on return:   ES:DI - pointer to new string (StrDelm only)
  3344.  
  3345. Flags  affected:       Carry = 1 if memory allocation error,  0 if okay
  3346.                (StrDelm only).
  3347.  
  3348. Example of Usage:
  3349.                les     di,  Str2Del
  3350.                mov     cx,  3          ; Delete starting at 4th char
  3351.                mov     ax,  5          ; Delete five characters
  3352.                StrDel                  ; Delete in place
  3353.  
  3354.                les     di,  Str2Del2
  3355.                mov     cx,  5
  3356.                mov     ax,  12
  3357.                StrDelm
  3358.                puts
  3359.                free
  3360.  
  3361.  
  3362. Description:  StrDel deletes characters from a string.  It works by computing
  3363.           the beginning and end of the deletion point.  Then it copies all
  3364.           the characters from the end of the deletion point to the end of
  3365.           the string (including the zero byte) to the beginning of the
  3366.           deletion point.  This covers up (thereby effectively deleting)
  3367.           the undesired characters in the string.
  3368.  
  3369.           Here are two degenerate cases to worry about -- 1) when you
  3370.           specify a deletion point which is beyond the end of the string;
  3371.           and 2) when the deletion point is within the string but the
  3372.           length of the deletion takes you beyond the end of the string.
  3373.           In the first case StrDel simply ignores the deletion request.  It
  3374.           does not modify the original string.  In the second case,
  3375.           StrDel simply deletes everything from the deletion point to the
  3376.           end of the string.
  3377.  
  3378.           StrDelm works just like StrDel except it does not delete the
  3379.           characters in place.  Instead, it creates a new string on the
  3380.           heap consisting of the characters up to the deletion point and
  3381.           those following the characters to delete.  It returns a pointer
  3382.           to the new string on the heap in ES:DI, assuming that it
  3383.           properly allocated the storage on the heap.
  3384.  
  3385. Include:               stdlib.a
  3386.  
  3387.  
  3388. Routine:  StrRev, StrRevm
  3389. -------------------------
  3390.  
  3391. Author:               Michael Blaszczak (.B  ekiM)
  3392.  
  3393. Category:             String Handling Routine
  3394.  
  3395. Registers on Entry:   ES:DI - pointer to string
  3396.  
  3397. Registers on return:  ES:DI - pointer to new string (StrRevm only).
  3398.  
  3399. Flags affected:       Carry  = 1 if memory allocation error, 0 if okay
  3400.               (StrRevm only).
  3401.  
  3402. Example of Usage:
  3403.  
  3404. Description:  StrRev reverses the characters in a string.  StrRev reverses,
  3405.           in place, the characters in the string that ES:SI points at.
  3406.           StrRevm creates a new string on the heap (which contains the
  3407.           characters in the string ES:DI points at, only reversed) and
  3408.           returns a pointer to the new string in ES:DI.  If StrRevm
  3409.           cannot allocate sufficient memory for the string, it returns
  3410.           with the carry flag set.
  3411.  
  3412.  
  3413. Include:              stdlib.a
  3414.  
  3415.  
  3416. Routine:  ToHex
  3417. ---------------
  3418.  
  3419. Category:             String Handling Routine/ Conversion Routine
  3420.  
  3421. Registers on Entry:   ES:DI - pointer to byte array
  3422.               BX-     memory base address for bytes
  3423.               CX-     number of entries in byte array
  3424.  
  3425. Registers on return:  ES:DI - pointer to Intel Hex format string.
  3426.  
  3427. Flags affected:       Carry  = 1 if memory allocation error, 0 if okay
  3428.            
  3429.  
  3430. Example of Usage:
  3431.  
  3432.         mov    bx, 100h    ;Put data at address 100h in hex file.
  3433.         mov    cx, 10h        ;Total of 16 bytes in this array.
  3434.         les    di, Buffer    ;Pointer to data bytes
  3435.         ToHex            ;Convert to Intel HEX string format.
  3436.         puts            ;Print it.
  3437.  
  3438. Description:  
  3439.  
  3440. ToHex converts a stream of binary values to Intel Hex format.  Intel HEX format
  3441. is a common ASCII data interchange format for binary data.  It takes the
  3442. following form:
  3443.  
  3444.     : BB HHLL RR DDDD...DDDD SS <cr> <lf>
  3445.  
  3446. (Note:spaces were added for clarity, they are not actually present in the
  3447. hex string)
  3448.  
  3449. BB is a pair of hex digits which represent the number of data bytes (The DD
  3450. entries) and is the value passed in CX.
  3451.  
  3452. HHLL is the hexadecimal load address for these data bytes (passed in BX).
  3453.  
  3454. RR is the record type.  ToHex always produces data records with the RR field
  3455. containing "00".  If you need to output other field types (usually just an
  3456. end record) you must create that string yourself.  ToHex will not do it.
  3457.  
  3458. DD...DD is the actual data in hex form.  This is the number of bytes specified
  3459. in the BB field.
  3460.  
  3461. SS is the two's complement of the checksum (which is the sum of the binary
  3462. values of the BB, HH, LL, RR, and all DD fields).
  3463.  
  3464. This routine allocates storage for the string on the heap and returns a pointer
  3465. to that string in ES:DI.
  3466.  
  3467. Include:              stdlib.a
  3468.  
  3469.  
  3470. Memory Management Routines
  3471. --------------------------
  3472.  
  3473. The stdlib memory management routines let you dynamically allocate storage on
  3474. the heap.  These routines are somewhat similar to those provided by the "C"
  3475. programming language.  However, these routines do not perform garbage
  3476. collection, as this would introduce too many restrictions and have a very
  3477. adverse effect on speed.
  3478.  
  3479. The following paragraph gives a description of how the memory management
  3480. routines work.  These routines may be updated in future revisions, however,
  3481. so you should never make assumptions about the structure of the memory
  3482. management record (described below) or else your code may not work on the
  3483. next revision.
  3484.  
  3485. The allocation/deallocation routines should be fairly fast.  Malloc and free
  3486. use a modified first/next fit algorithm which lets the system quickly find a
  3487. memory block of the desired size without undue fragmentation problems (average
  3488. case).  The memory manager data structure has an overhead of eight bytes
  3489. (meaning each malloc operation requires at least eight more bytes than you ask
  3490. for) and a granularity of 16 bytes.  The overhead (eight bytes) per allocated
  3491. block may seem rather high, but that is part of the price to pay for faster
  3492. malloc and free routines.  All pointers are far pointers and each new item is
  3493. allocated on a paragraph boundary.  The current memory manager routines always
  3494. allocate (n+8) bytes, rounding up to the next multiple of 16 if the result is
  3495. not evenly divisible by sixteen.  The first eight bytes of the structure are
  3496. used by the memory management routines, the remaining bytes are available for
  3497. use by the caller (malloc, et. al., return a pointer to the first byte beyond
  3498. the memory management overhead structure).
  3499.  
  3500.  
  3501.  
  3502.  
  3503. Routine:  MemInit
  3504. -----------------
  3505.  
  3506. Category:               Memory Management Routine
  3507.  
  3508. Registers on Entry:     DX - number of paragraphs to reserve
  3509.  
  3510. Globals Affected:       zzzzzzseg - segment name of the last segment in your
  3511.                     program
  3512.             PSP - public word variable which holds the PSP value
  3513.                   for your program
  3514.  
  3515. Registers on return:    CX - number of paragraphs actually reserved by MemInit
  3516.  
  3517. Flags affected:         Carry = 0 if no error.
  3518.             Carry = 1 if error; AX contains DOS error code.
  3519.  
  3520.  
  3521. Example of Usage:
  3522.                         ; Don't forget to set up PSP
  3523.                         ; and zzzzzzseg before calling
  3524.                         ; MemInit
  3525.             mov     dx, dx          ; Allocate all available RAM
  3526.             MemInit
  3527.             jc      MemoryError     ; CX contains the number of
  3528.                         ; paragraphs actually
  3529.                         ; allocated
  3530.  
  3531.  
  3532. Description:  This routine initializes the memory manager system.  You must
  3533.           call it before using any routines which call any of the memory
  3534.           manager procedures (since a good number of the stdlib routines
  3535.           call the memory manager, you should get in the habit of always
  3536.           calling this routine.)  The system will "die a horrible death"
  3537.           if you call a memory manager routine (like malloc) without first
  3538.           calling MemInit.
  3539.  
  3540.           This routine expects you to define (and set up) two global
  3541.           names: zzzzzzseg and PSP.  "zzzzzzseg" is a dummy segment which
  3542.           must be the name of the very last segment defined in your
  3543.           program.  MemInit uses the name of this segment to determine the
  3544.           address of the last byte in your program.  If you do not
  3545.           declare this segment last, the memory manager will overwrite
  3546.           anything which follows zzzzzzseg.  The "shell.asm" file
  3547.           provides you with a template for your programs which properly
  3548.           defines this segment.
  3549.  
  3550.           PSP should be a word variable which contains the program segment
  3551.           prefix value for your  program.  MS-DOS passes the PSP value to
  3552.           your program in the DS and ES registers.  You should save this
  3553.           value in the PSP variable.  Don't forget to make PSP a public
  3554.           symbol in your main program's source file.  The "shell.asm" file
  3555.           demonstrates how to properly set up this value.
  3556.  
  3557.           The DX register contnains the number of 16-byte paragraphs you
  3558.           want to reserve for the heap.  If DX contains zero, MemInit will
  3559.           allocate all of the available memory to the heap.  If your
  3560.           program is going to allow the user to run a copy of the command
  3561.           interpreter, or if your program is going to EXEC some other
  3562.           program, you should not allocate all storage to the heap.
  3563.           Instead, you should reserve  some memory for those programs.
  3564.           By setting DX to some value other than zero, you can tell MemInit
  3565.           how much memory you want to reserve for the heap.  All left over
  3566.           memory will be available for other system (or program) use.
  3567.           If the value in DX is larger than the amount of available RAM,
  3568.           MemInit will split the available memory in half and reserve half
  3569.           for the heap leaving the other half unallocated.  If you want to
  3570.           force this situation (to leave half available memory for other
  3571.           purposes), simply load DX with 0FFFFH before calling MemInit.
  3572.           There will never be this much memory available, so this will
  3573.           force MemInit to split the available RAM between the heap and
  3574.           unallocated storage.
  3575.  
  3576.           On return from MemInit, the CX register contains the number of
  3577.           paragraphs actually allocated.  You can use this value to see if
  3578.           MemInit has actually allocated the number of paragraphs you
  3579.           requested.  You  can also use this value to determine how much
  3580.           space is available when you elect to split the free space
  3581.           between the heap and the unallocated portions.
  3582.  
  3583.           If all goes well, this routine returns the carry flag clear.
  3584.           If a DOS memory manager error occurs, this routine returns the
  3585.           carry flag set and the DOS error code in the AX register.
  3586.  
  3587.  
  3588. Include:                stdlib.a
  3589.  
  3590.  
  3591. Routine:  Malloc
  3592. ----------------
  3593.  
  3594. Category:              Memory Management Routine
  3595.  
  3596. Registers on Entry:    CX - number of bytes to reserve
  3597.  
  3598. Registers on return:   CX - number of bytes actually reserved by Malloc
  3599.                ES:DI - ptr to 1st byte of memory allocated by Malloc
  3600.  
  3601. Flags affected:        Carry=0 if no error.
  3602.                Carry=1 if insufficient memory.
  3603.  
  3604. Example of Usage:
  3605.                mov     cx, 256
  3606.                Malloc
  3607.                jnc     GoodMalloc
  3608.                print   db    "Insufficient memory to continue.",cr,lf,0
  3609.                jmp   Quit
  3610.       GoodMalloc:  mov   es:[di], 0          ;Init string to NULL
  3611.  
  3612.  
  3613. Description:  Malloc is the workhorse routine you use to allocate a block of
  3614.           memory.  You give it the number of bytes you need and if it
  3615.           finds a block large enough, it will  allocate the requested
  3616.           amount and return a pointer to that block.
  3617.  
  3618.           Most memory managers require  a small amount of overhead for each
  3619.           block they allocate.  Stdlib's (current) memory manager requires
  3620.           an overhead of eight bytes.  Furthermore, the grainularity is 16
  3621.           bytes.  This means that Malloc always allocates blocks of memory
  3622.           in paragraph multiples.  Therefore, Malloc may actually reserve
  3623.           more storage than you specify. Therefore, the value returned in
  3624.           CX may be somewhat greater than the requested value.  By setting
  3625.           the minimum allocation size to a paragraph, however, the
  3626.           overhead is reduced and the speed of Malloc is improved by a
  3627.           considerable amount.
  3628.  
  3629.           Stdlib's memory management does not do any garbage collection.
  3630.           Doing so would place too many demands on Malloc's users.
  3631.           Therefore, it is quite possible for you to fragment memory with
  3632.           multiple calls to maloc, realloc, and free.  You could wind up in
  3633.           a situation where there is enough free memory to satisfy your
  3634.           request, but there isn't a single contiguous block large enough
  3635.           for the request.  Malloc treats this as an insufficient memory
  3636.           error and returns with the carry flag set.
  3637.  
  3638.           If Malloc cannot allocate a block of the requested size, it
  3639.           returns with the carry flag set.  In this situation, the contents
  3640.           of ES:DI is undefined.  Attempting to dereference this pointer
  3641.           will produce erratic and, perhaps, disasterous results.
  3642.  
  3643. Include:              stdlib.a
  3644.  
  3645.  
  3646. Routine:  Realloc
  3647. -----------------
  3648.  
  3649. Category:  Memory Management Routine
  3650.  
  3651. Registers on Entry:   CX - number of bytes to reserve
  3652.               ES:DI - pointer to block to  reallocate.
  3653.  
  3654. Registers on return:  CX - number of bytes actually reserved by Realloc.
  3655.               ES:DI - pointer to first byte of memory allocated by
  3656.                   Realloc.
  3657.  
  3658. Flags affected:       Carry = 0 if no error.
  3659.               Carry = 1 if insufficient memory.
  3660.  
  3661. Example of Usage:
  3662.             mov    cx, 1024    ;Change block size to 1K
  3663.             les    di, CurPtr    ;Get address of block into ES:DI
  3664.             realloc
  3665.             jc    BadRealloc
  3666.             mov    word ptr CurPtr, di
  3667.             mov    word ptr CurPtr+2, es
  3668.  
  3669.  
  3670. Description:  Realloc lets you change the size of an allocated block in the
  3671.           heap.  It allows you to make the block larger or smaller.
  3672.           If you make the  block smaller, Realloc simply frees (returns
  3673.           to the heap) any leftover bytes at the end of the block.  If
  3674.           you make the block larger, Realloc goes out and allocates a
  3675.           block of the requested size, copies the bytes form the old
  3676.           block to the beginning of the new block (leaving the bytes at
  3677.           the end of the new block uninitialized)), and then frees the
  3678.           old block.
  3679.  
  3680.  
  3681. Include:               stdlib.a
  3682.  
  3683.  
  3684. Routine:  Free
  3685. --------------
  3686.  
  3687. Category:               Memory Management Routine
  3688.  
  3689. Registers on Entry:     ES:DI - pointer to block to deallocate
  3690.  
  3691. Registers on return:    None
  3692.  
  3693. Flags affected:         Carry = 0 if no error.
  3694.             Carry = 1 if ES:DI doesn't point at a Free block.
  3695.  
  3696. Example of Usage:
  3697.             les     di, HeapPtr
  3698.             Free
  3699.  
  3700. Description:  Free (possibly) deallocates storage allocated on the heap by
  3701.           malloc or Realloc.  Free returns this storage to heap so other
  3702.           code can reuse it later.  Note, however, that Free doesn't
  3703.           always return storage to the heap.  The memory manager data
  3704.           structure keeps track of the number of pointers currently
  3705.           pointing at a block on the heap (see DupPtr, below).  If you've
  3706.           set up several pointers such that they point at the same block,
  3707.           Free will not deallocate the storage until you've freed all of
  3708.           the pointers which point at the block.
  3709.  
  3710.           Free usually returns an error code (carry flag = 1) if you
  3711.           attempt to Free a block which is not currently allocated or if
  3712.           you pass it a memory address which was not returned by malloc
  3713.           (or Realloc).  By no means is this routine totally robust.
  3714.           If you start calling free with arbitrary pointers in es:di
  3715.           (which happen to be pointing into the heap) it is possible,
  3716.           under certain circumstances, to confuse Free and it will attempt
  3717.           to free a block it really should not.
  3718.  
  3719.           This problem could be solved by adding a large amount of extra
  3720.           code to the free routine, but it would slow it down considerably.
  3721.           Therefore, a little safety has been sacrificed for a lot of
  3722.           speed.  Just make sure your code is correct and everything will
  3723.           be fine!
  3724.  
  3725.  
  3726. Include:               stdlib.a
  3727.  
  3728.  
  3729. Routine:  DupPtr
  3730. ----------------
  3731.  
  3732. Category:             Memory Manager Routine
  3733.  
  3734. Registers on Entry:   ES:DI - pointer to block
  3735.  
  3736. Registers on return:  None
  3737.  
  3738. Flags affected:       Carry = 0 if no error.
  3739.               Carry = 1 if es:di doesn't point at a free block.
  3740.  
  3741. Example of Usage:
  3742.               les     di,  Ptr
  3743.               DupPtr
  3744.  
  3745.  
  3746. Description:  DupPtr increments the pointer count for the block at the
  3747.           specifiied address.  Malloc sets this counter to one.  Free
  3748.           decrements it by one.  If free decrements the value and it
  3749.           becomes zero, free will release the storage to the heap for
  3750.           other use.  By using DupPtr you can tell the memory manager
  3751.           that you have several pointers pointing  at the same block
  3752.           and that it shouldn't deallocate the storage until you free
  3753.           all of those pointers.
  3754.  
  3755.  
  3756. Include:              stdlib.a
  3757.  
  3758.  
  3759. Routine:  IsInHeap
  3760. ------------------
  3761.  
  3762. Category:             Memory Management Routine
  3763.  
  3764. Registers on Entry:   ES:DI - pointer to a block
  3765.  
  3766. Registers on return:  None
  3767.  
  3768. Flags affected:       Carry = 0 if ES:DI is a valid pointer.
  3769.               Carry = 1 if not.
  3770.  
  3771. Example of Usage:
  3772.             les    di, MemPtr
  3773.             IsInHeap
  3774.             jc    NotInHeap
  3775.  
  3776. Description:  This routine lets you know if es:di contains the address of
  3777.           a byte in the heap somewhere.  It does not tell you if es:di
  3778.           contains a valid pointer returned by malloc (see IsPtr, below).
  3779.           For example, if es:di contains the address of some particular
  3780.           element of an array (not necessarily the first element)
  3781.           allocated on the heap, IsInHeap will return with the carry clear
  3782.           denoting that the es:di points somewhere in the heap.  Keep in
  3783.           mind that calling this routine does not validate the pointer;
  3784.           it could be pointing at a byte which is part of the memory
  3785.           manager data structure rather than at actual data (since the
  3786.           memory manager maintains that informatnion within the
  3787.           bounds of the heap). This routine is mainly useful for seeing
  3788.           if something is allocated on the heap as opposed to somewhere
  3789.           else (like your code, data, or stack segment).
  3790.  
  3791.  
  3792. Include:              stdlib.a
  3793.  
  3794.  
  3795. Routine:  IsPtr
  3796. ---------------
  3797.  
  3798. Category:               Memory Management Routine
  3799.  
  3800. Registers on Entry:     ES:DI - pointer to block
  3801.  
  3802. Registers on return:    None
  3803.  
  3804. Flags affected:         Carry = 0 if es:di is a valid pointer.
  3805.             Carry = 1 if not.
  3806.  
  3807. Example of Usage:
  3808.             les    di, MemPtr
  3809.             IsPtr
  3810.             jc    NotAPtr
  3811.  
  3812.  
  3813.  
  3814. Description:  IsPtr is much more specific than IsInHeap.  This routine returns
  3815.           the carry flag clear if and only if es:di contains the address
  3816.           of a properly allocated (and currently allocated) block on the
  3817.           heap.  This pointer must be a value returned by Malloc, Realloc,
  3818.           or DupPtr and that block must be currently allocated for IsPtr
  3819.           to return the carry flag clear.
  3820.  
  3821.  
  3822. Include:                stdlib.a
  3823.  
  3824.  
  3825. Character Set Routines
  3826. ----------------------
  3827.  
  3828. The character set routines let you deal with groups of characters as a set
  3829. rather than a string.  A set is an unordered collection of objects where
  3830. membership (presence or absence) is the only important quality.  The stdlib
  3831. set routines were designed to let you quickly check if an ASCII character is
  3832. in a set, to quickly add characters to a set or remove characters from a set.
  3833. These operations are the ones most commonly used on character sets.  The
  3834. other operations (like union, intersection, difference, etc.) are useful, but
  3835. are not as popular as the former routines.  Therefore, the data structure
  3836. has been optimized for sets to handle the membership and add/delete operations
  3837. at the slight expense of the others.
  3838.  
  3839. Character sets are implemented via bit vectors.  A "1" bit means that an item
  3840. is present in the set and a "0" bit means that the item is absent from the
  3841. set.  The most common implementation of a character set is to use thirty-two 
  3842. consecutive bytes, eight bytes per, giving 256 bits (one bit for each char-
  3843. acter in the character set).  While this makes certain operations (like 
  3844. assignment, union, intersection, etc.) fast and convenient, other operations
  3845. (membership, add/remove items) run much slower.  Since these are the more 
  3846. important operations, a different data structure is used to represent sets.  
  3847. A faster approach is to simply use a byte value for each item in the set.  
  3848. This offers a major advantage over the thirty-two bit scheme:  for operations 
  3849. like membership it is very fast (since all you have got to do is index into 
  3850. an array and test the resulting value).  It has two drawbacks:  first, oper-
  3851. ations like set assignment, union, difference, etc., require 256 operations 
  3852. rather than thirty-two; second, it takes eight times as much memory.
  3853.  
  3854. The first drawback, speed, is of little consequence.  You will rarely use the
  3855. the operations so affected, so the fact that they run a little slower will be
  3856. of little consequence.  Wasting 224 bytes is a problem, however.  Especially
  3857. if you have a lot of character sets.
  3858.  
  3859. The approach used here is to allocate 272 bytes.  The first eight bytes con-
  3860. tain bit masks, 1, 2, 4, 8, 16, 32, 64, 128.  These masks tell you which bit
  3861. in the following 264 bytes is associated with the set.  This facilitates 
  3862. putting eight sets into 272 bytes (34 bytes per character set).  This provides
  3863. almost the speed of the 256-byte set with only a two byte overhead.  In the
  3864. stdlib.a file there is a macro that lets you define a group of character
  3865. sets:  set.  The macro is used as follows:
  3866.  
  3867.     set set1, set2, set3, ... , set8
  3868.  
  3869. You must supply between one and eight labels in the operand field.  These are
  3870. the names of the sets you want to create.  The set macro automatically 
  3871. attaches these labels to the appropriate mask bytes in the set.  The actual
  3872. bit patterns for the set begin eight bytes later (from each label).  There-
  3873. fore, the byte corresponding to chr(0) is staggered by one byte for each
  3874. set (which explains the other eight bytes needed above and beyond the 256 
  3875. required for the set).  When using the set manipulation routines, you should
  3876. always pass the address of the mask byte (i.e., the seg/offset of one of the 
  3877. labels above) to the particular set manipulation routine you are using. 
  3878. Passing the address of the structure created with the macro above will 
  3879. reference only the first set in the group.
  3880.  
  3881. Note that you can use the set operations for fast pattern matching appli-
  3882. cations.  The set membership operation for example, is much faster that the 
  3883. strspan routine found in the string package.  Proper use of character sets
  3884. can produce a program which runs much faster than some of the equivalent
  3885. string operations.
  3886.  
  3887.  
  3888. Routine:  Createsets
  3889. --------------------
  3890.  
  3891. Category:             Character Set Routine
  3892.  
  3893. Registers on Entry:   no parameters passed
  3894.  
  3895. Registers on return:  ES:DI - pointer to eight sets
  3896.  
  3897. Flags affected:       Carry = 0 if no error. Carry = 1 if insufficient
  3898.               memory to allocate storage for sets.
  3899.  
  3900. Example of Usage:
  3901.               Createsets
  3902.               jc      NoMemory
  3903.               mov     word ptr SetPtr,   di
  3904.               mov     word ptr SetPtr+2, es
  3905.  
  3906. Description:  Createsets allocates 272 bytes on the heap.   This is sufficient
  3907.           room for eight character sets.  It then initializes the first
  3908.           eight bytes of this storage with the proper mask values for
  3909.           each set.  Location es:0[di] gets set to 1, location es:1[di]
  3910.           gets 2, location es:2[di] gets 4, etc.  The Createsets routine
  3911.           also initializes all of the sets to the empty set by clearing
  3912.           all the bits to zero.
  3913.  
  3914. Include:              stdlib.a
  3915.  
  3916.  
  3917. Routine:  EmptySet
  3918. ------------------
  3919.  
  3920. Category:             Character Set Routine
  3921.  
  3922. Registers on Entry:   ES:DI - pointer to first byte of desired set
  3923.  
  3924. Registers on return:  None
  3925.  
  3926. Flags affected:          None
  3927.  
  3928. Example of Usage:
  3929.               les     di,  SetPtr
  3930.               add     di,  3          ; Point at 4th set in group.
  3931.               Emptyset
  3932.  
  3933.  
  3934. Description:  Emptyset clears out the bits in a character set to zero
  3935.           (thereby setting it to the empty set).  Upon entry, es:di must
  3936.           point at the first byte of the character set you want to clear.
  3937.           Note that this is not the address returned by Createsets.  The
  3938.           first eight bytes of a character set structure are the
  3939.           addresses of eight different sets.  ES:DI must point at one of
  3940.           these bytes upon entry into Emptyset.
  3941.  
  3942. Include:              stdlib.a
  3943.  
  3944.  
  3945. Routine:  Rangeset
  3946. ------------------
  3947.  
  3948. Category:             Character Set Routine
  3949.  
  3950. Registers on entry:   ES:DI (contains the address of the first byte of the set)
  3951.               AL    (contains the lower bound of the items)
  3952.               AH    (contains the upper bound of the items)
  3953.  
  3954. Registers on return:  None
  3955.  
  3956. Flags affected:       None
  3957.  
  3958. Example of Usage:
  3959.               lea di, SetPtr
  3960.               add di, 4
  3961.               mov al, 'A'
  3962.               mov ah, 'Z'
  3963.               rangeset
  3964.  
  3965.  
  3966. Description:  This routine adds a range of values to a set with ES:DI as the
  3967.           pointer to the set, AL as the lower bound of the set, and
  3968.           AH as the upper bound of the set (AH has to be greater than
  3969.           AL, otherwise, there will an error).
  3970.  
  3971. Include:              stdlib.a
  3972.  
  3973.  
  3974. Routine:  Addstr (l)
  3975. --------------------
  3976.  
  3977. Category:             Character Set Routine
  3978.  
  3979. Registers on Entry:   ES:DI- pointer to first byte of desired set
  3980.               DX:SI- pointer to string to add to set (Addstr only)
  3981.               CS:RET-pointer to string to add to set (Addstrl only)
  3982.  
  3983. Registers on Return:  None
  3984.  
  3985. Flags Affected:       None
  3986.  
  3987. Example of Usage:
  3988.               les     di, SetPtr
  3989.               add     di, 1           ;Point at 2nd set in group.
  3990.               mov     dx, seg CharStr ;Pointer to string
  3991.               lea     si, CharStr     ; chars to add to set.
  3992.               addstr                  ;Union in these characters.
  3993. ;
  3994.               les     di, SetPtr      ;Point at first set in group.
  3995.               addstrl
  3996.               db      "AaBbCcDdEeFf0123456789",0
  3997. ;
  3998.  
  3999.  
  4000. Description:  Addstr lets you add a group of characters to a set by
  4001.           specifying a string containing the characters you want in
  4002.           the set.  To Addstr you pass a pointer to a zero-terminated
  4003.           string in dx:si.  Addstr will add (union) each character
  4004.           from this string into the set.
  4005.  
  4006.           Addstrl works the same way except you pass the string as
  4007.           a literal string constant in the code stream rather than
  4008.           via ES:DI.
  4009.  
  4010. Include:              stdlib.a
  4011.  
  4012.  
  4013. Routine:  Rmvstr (l)
  4014. --------------------
  4015.  
  4016.  
  4017. Category:             Character Set Routine
  4018.  
  4019.  
  4020. Registers on entry:   ES:DI contains the address of first byte of a set
  4021.               DX:SI contains the address of string to be removed
  4022.                  from a set (Rmvstr only)
  4023.               CS:RET pointer to string to add to set (Rmvstrl only)
  4024.  
  4025.  
  4026. Registers on return:  None
  4027.  
  4028.  
  4029. Flags affected:       None
  4030.  
  4031.  
  4032. Example of Usage:
  4033.               les     di, SetPtr
  4034.               mov     dx, seg CharStr
  4035.               lea     si, CharStr
  4036.               rmvstr
  4037.  
  4038.               mov     dx, seg CharStr
  4039.               lea     si, CharStr
  4040.               rmvstrl
  4041.               db          "ABCDEFG",0
  4042.  
  4043.  
  4044. Description:  This routine is to remove a string from a set with ES:DI
  4045.           pointing to its first byte, and DX:SI pointing to the
  4046.           string to be removed from the set.
  4047.  
  4048.           For Rmvstrl, the string of characters to remove from the
  4049.           set follows the call in the code stream.
  4050.  
  4051. Include:              stdlib.a
  4052.  
  4053.  
  4054. Routine:  AddChar
  4055. -----------------
  4056.  
  4057. Category:             Character Set Routine
  4058.  
  4059. Registers on Entry:   ES:DI- pointer to first byte of desired set
  4060.               AL- character to add to the set
  4061.  
  4062. Registers on Return:  None
  4063.  
  4064. Flags affected:       None
  4065.  
  4066. Example of Usage:
  4067.               les     di, SetPtr
  4068.               add     di, 1           ;Point at 2nd set in group.
  4069.               mov     al, Ch2Add      ;Character to add to set.
  4070.               addchar
  4071.  
  4072.  
  4073. Description:  AddChar lets you add a single character (passed in AL)
  4074.           to a set.
  4075.  
  4076. Include:              stdlib.a
  4077.  
  4078.  
  4079. Routine:  Rmvchar
  4080. -----------------
  4081.  
  4082. Category:             Character Set Routine
  4083.  
  4084. Registers on entry:   ES:DI (contains the address of first byte of a set)
  4085.               AL    (contains the character to be removed)
  4086.  
  4087. Registers on return:  None
  4088.  
  4089. Flags affected:          None
  4090.  
  4091. Example of Usage:
  4092.               lea di, SetPtr
  4093.               add di, 7        ;Point at eighth set in group.
  4094.               mov al, Ch2Rmv
  4095.               Rmvchar
  4096.  
  4097. Description:  This routine removes the character in AL from a set.
  4098.           ES:SI points to the set's mask byte. The corresponding
  4099.           bit in the set is cleared to zero.
  4100.  
  4101. Include:              stdlib.a
  4102.  
  4103.  
  4104. Routine:  Member
  4105. ----------------
  4106.  
  4107. Category:             Character Set Routine
  4108.  
  4109. Registers on entry:   ES:DI (contains the address of first byte of a set)
  4110.               AL    (contains the character to be compared)
  4111.  
  4112. Registers on return:  None
  4113.  
  4114. Flags affected:       Zero flag (Zero = 1 if the character is in the set
  4115.                  Zero = 0 if the character is not in the set)
  4116.  
  4117. Example of Usage:
  4118.               les di, SetPtr
  4119.               add di, 1
  4120.               mov al, 'H'
  4121.               member
  4122.               je IsInSet
  4123.  
  4124.  
  4125. Description:  Member is used to find out if the character in AL is in a set
  4126.           with ES:DI pointing to its mask byte. If the character is in
  4127.           the set, the zero flag is set to 1. If not, the zero flag is
  4128.           set to zero.
  4129.  
  4130. Include:              stdlib.a
  4131.  
  4132.  
  4133. Routine:  CopySet
  4134. -----------------
  4135.  
  4136. Category:            Character Set Routine
  4137.  
  4138. Register on entry:   ES:DI- pointer to first byte of destination set.
  4139.              DX:SI- pointer to first byte of source set.
  4140.  
  4141. Register on Return:  None
  4142.  
  4143. Flags affected:      None
  4144.  
  4145. Example of Usage:
  4146.              les     di, SetPtr
  4147.              add     di, 7           ;Point at 8th set in group.
  4148.              mov     dx, seg SetPtr2 ;Point at first set in group.
  4149.              lea     si, SetPtr2
  4150.              copyset
  4151.  
  4152.  
  4153. Description:  CopySet copies the items from one set to another.  This is a
  4154.           straight assignment, not a union operation.  After the
  4155.           operation, the destination set is identical to the source set,
  4156.           both in terms of the element present in the set and absent
  4157.           from the set.
  4158.  
  4159.  
  4160. Include:             stdlib.a
  4161.  
  4162.  
  4163. Routine:  SetUnion
  4164. ------------------
  4165.  
  4166. Category:            Character Set Routine
  4167.  
  4168. Register on entry:   ES:DI - pointer to first byte of destination set.
  4169.              DX:SI - pointer to first byte of source set.
  4170.  
  4171. Register on return:  None
  4172.  
  4173. Flags affected:      None
  4174.  
  4175. Example of Usage:    les   di, SetPtr
  4176.              add   di, 7              ;point at 8th set in group.
  4177.              mov   dx, seg SetPtr2    ;point at 1st set in group.
  4178.              lea   si, sSetPtr2
  4179.              unionset
  4180.  
  4181.  
  4182. Description:  The SetUnion routine computes the union of two sets.
  4183.           That is, it adds all of the items present in a source set
  4184.           to a destination set.  This operation preserves items
  4185.           present in the destination set before the SetUnion
  4186.           operation.
  4187.  
  4188. Include:             stdlib.a
  4189.  
  4190.  
  4191. Routine:  SetIntersect
  4192. ----------------------
  4193.  
  4194. Category:            Character Set Routine
  4195.  
  4196. Register on entry:   ES:DI - pointer to first byte of destination set.
  4197.              DX:SI - pointer to first byte of source set.
  4198.  
  4199. Register on return:  None
  4200.  
  4201. Flags affected:      None
  4202.  
  4203. Example of Usage:
  4204.              les   di, SetPtr
  4205.              add   di, 7              ;point at 8th set in group.
  4206.              mov   dx, seg SetPtr2    ;point at 1st set in group.
  4207.              lea   si, SetPtr2
  4208.              setintersect
  4209.  
  4210. Description:  SetIntersect computes the intersection of two sets, leaving
  4211.           the result in the destination set.  The new set consists
  4212.           only of those items which previously appeared in
  4213.           both the source and destination sets.
  4214.  
  4215. Include:             stdlib.a
  4216.  
  4217.  
  4218. Routine:  SetDifference
  4219. -----------------------
  4220.  
  4221. Category:            Character Set Routine
  4222.  
  4223. Register on entry:   ES:DI - pointer to the first byte of destination set.
  4224.              DX:SI - pointer to the first byte of the source set.
  4225.  
  4226. Register on return:  None
  4227.  
  4228. Flags affected:      None
  4229.  
  4230. Example of Usage:
  4231.              les   di, SetPtr
  4232.              add   di, 7               ;point at 8th set in group.
  4233.              mov   dx, seg SetPtr2     ;point at 1st set in group.
  4234.              lea   si, SetPtr2
  4235.              setdifference
  4236.  
  4237.  
  4238. Description:  SetDifference computes the result of (ES:DI) := (ES:DI) -
  4239.           (DX:SI).  The destination set is left with its original
  4240.           items minus those items which are also in the source set.
  4241.  
  4242. Include:             stdlib.a
  4243.  
  4244.  
  4245. Routine:  Nextitem
  4246. ------------------
  4247.  
  4248. Category:             Character Set Routine
  4249.  
  4250. Registers on entry:   ES:DI (contains the address of first byte of the set)
  4251.  
  4252. Registers on return:  AL (contains the first item in the set)
  4253.  
  4254. Flags affected:       None
  4255.  
  4256. Example of Usage:
  4257.               les di, SetPtr
  4258.               add di, 7        ;Point at eighth set in group.
  4259.               nextitem
  4260.  
  4261.  
  4262. Description:  Nextitem is the routine to search the first character (item)
  4263.           in the set with ES:DI pointing to its mask byte. AL will
  4264.           return the character in the set. If the set is empty, AL
  4265.           will contain zero.
  4266.  
  4267. Include:              stdlib.a
  4268.  
  4269.  
  4270. Routine:  Rmvitem
  4271. -----------------
  4272.  
  4273. Category:             Character Set Routine
  4274.  
  4275. Registers on entry:   ES:DI (contains the address fo first byte of the set)
  4276.  
  4277. Registers on return:  AL (contains the first item in the set)
  4278.  
  4279. Flags affected:       None
  4280.  
  4281. Example of Usage:
  4282.               les di, SetPtr
  4283.               add di, 7
  4284.               rmvitem
  4285.  
  4286. Description:  Rmvitem locates the first available item in the set and
  4287.           removes it with ES:DI pointing to its mask byte. AL will
  4288.           return the item removed. If the set is empty, AL will
  4289.           return zero.
  4290.  
  4291. Include:              stdlib.a
  4292.  
  4293.  
  4294.  
  4295. Floating Point Routines
  4296. -----------------------
  4297.  
  4298. The floating point routines provide a basic floating point package for
  4299. 80x86 assembly language users.  The floating point package deals with
  4300. four different floating point formats: IEEE 32-bit, 64-bit, and 80-bit
  4301. formats, and an internal 81-bit format.  The external formats mostly
  4302. support the IEEE standard except for certain esoteric values such as
  4303. denormalized numbers, NaNs, infinities, and other such cases.
  4304.  
  4305. The package provides two "pseudo-registers", a floating point accumulator
  4306. and a floating point operand.  It provides routines to load and store these
  4307. pseudo-registers from memory operands (using the various formats) and then
  4308. all other operations apply to these two operands.  All computations use the
  4309. internal 81-bit floating point format.  The package automatically converts
  4310. between the internal format and the external format when loading and storing
  4311. values.
  4312.  
  4313. Do not write code which assumes the internal format is 81 bits.  This format
  4314. will change in the near future when I get a chance to add guard bits to
  4315. all the computations.  If your code assumes 81 bits, it will break at that
  4316. point.  Besides, there is no reason your code should count on the size of
  4317. the internal operations anyway.  Stick with the IEEE formats and you'll
  4318. be much better off (since your code can be easily upgraded to deal with
  4319. numeric coprocessors).
  4320.  
  4321. WARNING: These routines have not been sufficiently tested as of 10/10/91.
  4322. Use them with care.  Report any problems with these routines to Randy Hyde
  4323. via the electronic addresses provided in this document or by sending a
  4324. written report to UC Riverside.  As I get more time, I will further test
  4325. these routines and add additional functions to the package.
  4326.  
  4327.                     *** Randy Hyde
  4328.  
  4329.  
  4330.  
  4331. Routine:  lsfpa
  4332. ---------------
  4333.  
  4334. Category:             Floating point Routine
  4335.  
  4336. Registers on entry:   ES:DI points at a single precision (32-bit) value to load
  4337.  
  4338. Registers on return:  None
  4339.  
  4340. Flags affected:       None
  4341.  
  4342. Example of Usage:
  4343.             les di, FPValue
  4344.             lsfpa
  4345.  
  4346. Description:    LSFPA loads a single precision floating point value into the
  4347.         internal floating point accumulator.  It also converts the
  4348.         32-bit format to the internal 81-bit format used by the
  4349.         floating point package.
  4350.  
  4351. Include:    stdlib.a
  4352.  
  4353. Routine:  ssfpa
  4354. ---------------
  4355.  
  4356. Category:             Floating point Routine
  4357.  
  4358. Registers on entry:   ES:DI points at a single precision (32-bit) value where
  4359.               this routine should store the floating point acc.
  4360.  
  4361. Registers on return:  None
  4362.  
  4363. Flags affected:       Carry set if conversion error.
  4364.  
  4365. Example of Usage:
  4366.             les di, FPValue
  4367.             ssfpa
  4368.  
  4369. Description:    SSFPA stores the floating point accumulator into a single
  4370.         precision variable in memory (pointed at by ES:DI).  It
  4371.         converts the value from the 81-bit format to the 32-bit
  4372.         value before storing the result.   The 64-bit mantissa used
  4373.         by the FP package is rounded to 24 bits during the store.
  4374.         The exponent could be out of range.  If this occurs, SSFPA
  4375.         returns with the carry flag set.
  4376.  
  4377. Include:    stdlib.a
  4378.  
  4379.  
  4380. Routine:  ldfpa
  4381. ---------------
  4382.  
  4383. Category:             Floating point Routine
  4384.  
  4385. Registers on entry:   ES:DI points at a double precision (64-bit) value to load
  4386.  
  4387. Registers on return:  None
  4388.  
  4389. Flags affected:       None
  4390.  
  4391. Example of Usage:
  4392.             les di, FPValue
  4393.             ldfpa
  4394.  
  4395. Description:    LDFPA loads a double precision floating point value into the
  4396.         internal floating point accumulator.  It also converts the
  4397.         64-bit format to the internal 81-bit format used by the
  4398.         floating point package.
  4399.  
  4400. Include:    stdlib.a
  4401.  
  4402. Routine:  sdfpa
  4403. ---------------
  4404.  
  4405. Category:             Floating point Routine
  4406.  
  4407. Registers on entry:   ES:DI points at a double precision (64-bit) value where
  4408.               this routine should store the floating point acc.
  4409.  
  4410. Registers on return:  None
  4411.  
  4412. Flags affected:       Carry set if conversion error.
  4413.  
  4414. Example of Usage:
  4415.             les di, FPValue
  4416.             sdfpa
  4417.  
  4418. Description:    SDFPA stores the floating point accumulator into a double
  4419.         precision variable in memory (pointed at by ES:DI).  It
  4420.         converts the value from the 81-bit format to the 64-bit
  4421.         value before storing the result.   The 64-bit mantissa used
  4422.         by the FP package is rounded to 51 bits during the store.
  4423.         The exponent could be out of range.  If this occurs, SDFPA
  4424.         returns with the carry flag set.
  4425.  
  4426. Include:    stdlib.a
  4427.  
  4428.  
  4429. Routine:  lefpa
  4430. ---------------
  4431.  
  4432. Category:             Floating point Routine
  4433.  
  4434. Registers on entry:   ES:DI points at an extended precision (80-bit) value to
  4435.               load
  4436.  
  4437. Registers on return:  None
  4438.  
  4439. Flags affected:       None
  4440.  
  4441. Example of Usage:
  4442.             les di, FPValue
  4443.             lefpa
  4444.  
  4445. Description:    LEFPA loads an extended precision floating point value into
  4446.         the internal floating point accumulator.  It also converts the
  4447.         80-bit format to the internal 81-bit format used by the
  4448.         floating point package.
  4449.  
  4450. Include:    stdlib.a
  4451.  
  4452.  
  4453. Routine:  lefpal
  4454. ----------------
  4455.  
  4456. Category:             Floating point Routine
  4457.  
  4458. Registers on entry:   CS:RET points at an extended precision (80-bit) value to
  4459.               load
  4460.  
  4461. Registers on return:  None
  4462.  
  4463. Flags affected:       None
  4464.  
  4465. Example of Usage:
  4466.             lefpal
  4467.             dt    1.345e-3
  4468.  
  4469. Description:    LEFPAL loads an extended precision floating point value into
  4470.         the internal floating point accumulator.  It also converts the
  4471.         80-bit format to the internal 81-bit format used by the
  4472.         floating point package.
  4473.  
  4474.         Unlike LEFPA, LEFPAL gets its operand directly from the code
  4475.         stream.  You must follow the call to lefpal with a ten-byte
  4476.         (80-bit) floating point constant.
  4477. Include:    stdlib.a
  4478.  
  4479. Routine:  sefpa
  4480. ---------------
  4481.  
  4482. Category:             Floating point Routine
  4483.  
  4484. Registers on entry:   ES:DI points at an extended precision (80-bit) value
  4485.               where this routine should store the floating point acc.
  4486.  
  4487. Registers on return:  None
  4488.  
  4489. Flags affected:       Carry set if conversion error.
  4490.  
  4491. Example of Usage:
  4492.             les di, FPValue
  4493.             sefpa
  4494.  
  4495. Description:    SEFPA stores the floating point accumulator into an extended
  4496.         precision variable in memory (pointed at by ES:DI).  It
  4497.         converts the value from the 81-bit format to the 80-bit
  4498.         value before storing the result.
  4499.  
  4500.         The exponent could be out of range.  If this occurs, SEFPA
  4501.         returns with the carry flag set.
  4502.  
  4503. Include:    stdlib.a
  4504.  
  4505.  
  4506. Routine:  lsfpo
  4507. ---------------
  4508.  
  4509. Category:             Floating point Routine
  4510.  
  4511. Registers on entry:   ES:DI points at a single precision (32-bit) value to load
  4512.  
  4513. Registers on return:  None
  4514.  
  4515. Flags affected:       None
  4516.  
  4517. Example of Usage:
  4518.             les di, FPValue
  4519.             lsfpo
  4520.  
  4521. Description:    LSFPA loads a single precision floating point value into the
  4522.         internal floating point operand.  It also converts the
  4523.         32-bit format to the internal 81-bit format used by the
  4524.         floating point package.
  4525.  
  4526. Include:    stdlib.a
  4527.  
  4528.  
  4529. Routine:  ldfpo
  4530. ---------------
  4531.  
  4532. Category:             Floating point Routine
  4533.  
  4534. Registers on entry:   ES:DI points at a double precision (64-bit) value to load
  4535.  
  4536. Registers on return:  None
  4537.  
  4538. Flags affected:       None
  4539.  
  4540. Example of Usage:
  4541.             les di, FPValue
  4542.             ldfpo
  4543.  
  4544. Description:    LDFPO loads a double precision floating point value into the
  4545.         internal floating point operand.  It also converts the
  4546.         64-bit format to the internal 81-bit format used by the
  4547.         floating point package.
  4548.  
  4549. Include:    stdlib.a
  4550.  
  4551.  
  4552. Routine:  lefpo
  4553. ---------------
  4554.  
  4555. Category:             Floating point Routine
  4556.  
  4557. Registers on entry:   ES:DI points at an extended precision (80-bit) value to
  4558.               load
  4559.  
  4560. Registers on return:  None
  4561.  
  4562. Flags affected:       None
  4563.  
  4564. Example of Usage:
  4565.             les di, FPValue
  4566.             lefpo
  4567.  
  4568. Description:    LEFPO loads an extended precision floating point value into
  4569.         the internal floating point operand.  It also converts the
  4570.         80-bit format to the internal 81-bit format used by the
  4571.         floating point package.
  4572.  
  4573. Include:    stdlib.a
  4574.  
  4575.  
  4576. Routine:  lefpol
  4577. ----------------
  4578.  
  4579. Category:             Floating point Routine
  4580.  
  4581. Registers on entry:   CS:RET points at an extended precision (80-bit) value to
  4582.               load
  4583.  
  4584. Registers on return:  None
  4585.  
  4586. Flags affected:       None
  4587.  
  4588. Example of Usage:
  4589.             lefpal
  4590.             dt    1.345e-3
  4591.  
  4592. Description:    LEFPOL loads an extended precision floating point value into
  4593.         the internal floating point operand.  It also converts the
  4594.         80-bit format to the internal 81-bit format used by the
  4595.         floating point package.
  4596.  
  4597.         Unlike LEFPO, LEFPOL gets its operand directly from the code
  4598.         stream.  You must follow the call to lefpal with a ten-byte
  4599.         (80-bit) floating point constant.
  4600. Include:    stdlib.a
  4601.  
  4602.  
  4603. Routine:  itof
  4604. --------------
  4605.  
  4606. Category:             Floating point Routine
  4607.  
  4608. Registers on entry:   AX contains a signed integer value
  4609.  
  4610. Registers on return:  None
  4611.  
  4612. Flags affected:       None
  4613.  
  4614. Example of Usage:
  4615.             mov    ax, -1234
  4616.             itof
  4617.  
  4618. Description:    ITOF converts the 16-bit signed integer in AX to a floating
  4619.         point value, storing the result in the floating point
  4620.         accumuator.
  4621.  
  4622. Include:    stdlib.a
  4623.  
  4624.  
  4625. Routine:  utof
  4626. --------------
  4627.  
  4628. Category:             Floating point Routine
  4629.  
  4630. Registers on entry:   AX contains an unsigned integer value
  4631.  
  4632. Registers on return:  None
  4633.  
  4634. Flags affected:       None
  4635.  
  4636. Example of Usage:
  4637.             mov    ax, -1234
  4638.             itof
  4639.  
  4640. Description:    UTOF converts the 16-bit unsigned integer in AX to a floating
  4641.         point value, storing the result in the floating point
  4642.         accumuator.
  4643.  
  4644. Include:    stdlib.a
  4645.  
  4646.  
  4647. Routine:  ultof
  4648. ---------------
  4649.  
  4650. Category:             Floating point Routine
  4651.  
  4652. Registers on entry:   DX:AX contains an unsigned 32-bit integer value
  4653.  
  4654. Registers on return:  None
  4655.  
  4656. Flags affected:       None
  4657.  
  4658. Example of Usage:
  4659.             mov    dx, word ptr val32+2
  4660.             mov    ax, word ptr val32
  4661.             ultof
  4662.  
  4663. Description:    ULTOF converts the 32-bit unsigned integer in DX:AX to a
  4664.         floating point value, storing the result in the floating
  4665.         point accumuator.
  4666.  
  4667. Include:    stdlib.a
  4668.  
  4669.  
  4670. Routine:  ltof
  4671. --------------
  4672.  
  4673. Category:             Floating point Routine
  4674.  
  4675. Registers on entry:   DX:AX contains a signed 32-bit integer value
  4676.  
  4677. Registers on return:  None
  4678.  
  4679. Flags affected:       None
  4680.  
  4681. Example of Usage:
  4682.             mov    dx, word ptr val32+2
  4683.             mov    ax, word ptr val32
  4684.             ltof
  4685.  
  4686. Description:    LTOF converts the 32-bit signed integer in DX:AX to a
  4687.         floating point value, storing the result in the floating
  4688.         point accumuator.
  4689.  
  4690. Include:    stdlib.a
  4691.  
  4692.  
  4693. Routine:  ftoi
  4694. --------------
  4695.  
  4696. Category:             Floating point Routine
  4697.  
  4698. Registers on entry:   None
  4699.  
  4700. Registers on return:  AX contains 16-bit signed integer
  4701.  
  4702. Flags affected:       Carry is set if conversion error occurs.
  4703.  
  4704. Example of Usage:
  4705.             ftoi
  4706.             puti        ;Print AX as integer value
  4707.  
  4708.  
  4709. Description:    FTOI converts the floating point accumulator value to a
  4710.         16-bit signed integer and returns the result in AX.  If
  4711.         the floating point number will not fit in AX, FTOI returns
  4712.         with the carry flag set.
  4713.  
  4714. Include:    stdlib.a
  4715.  
  4716.  
  4717. Routine:  ftou
  4718. --------------
  4719.  
  4720. Category:             Floating point Routine
  4721.  
  4722. Registers on entry:   None
  4723.  
  4724. Registers on return:  AX contains 16-bit unsigned integer
  4725.  
  4726. Flags affected:       Carry is set if conversion error occurs.
  4727.  
  4728. Example of Usage:
  4729.             ftou
  4730.             putu        ;Print AX as an unsigned value
  4731.  
  4732.  
  4733. Description:    FTOU converts the floating point accumulator value to a
  4734.         16-bit unsigned integer and returns the result in AX.  If
  4735.         the floating point number will not fit in AX, FTOU returns
  4736.         with the carry flag set.
  4737.  
  4738. Include:    stdlib.a
  4739.  
  4740.  
  4741. Routine:  ftol
  4742. --------------
  4743.  
  4744. Category:             Floating point Routine
  4745.  
  4746. Registers on entry:   None
  4747.  
  4748. Registers on return:  DX:AX contains a 32-bit signed integer
  4749.  
  4750. Flags affected:       Carry is set if conversion error occurs.
  4751.  
  4752. Example of Usage:
  4753.             ftol
  4754.             putl        ;Print DX:AX as integer value
  4755.  
  4756.  
  4757. Description:    FTOL converts the floating point accumulator value to a
  4758.         32-bit signed integer and returns the result in DX:AX.  If
  4759.         the floating point number will not fit in DX:AX, FTOL returns
  4760.         with the carry flag set.
  4761.  
  4762. Include:    stdlib.a
  4763.  
  4764.  
  4765. Routine:  ftoul
  4766. ---------------
  4767.  
  4768. Category:             Floating point Routine
  4769.  
  4770. Registers on entry:   None
  4771.  
  4772. Registers on return:  DX:AX contains a 32-bit unsigned integer
  4773.  
  4774. Flags affected:       Carry is set if conversion error occurs.
  4775.  
  4776. Example of Usage:
  4777.             ftoul
  4778.             putul        ;Print DX:AX as an integer value
  4779.  
  4780.  
  4781. Description:    FTOUL converts the floating point accumulator value to a
  4782.         32-bit unsigned integer and returns the result in DX:AX.  If
  4783.         the floating point number will not fit in DX:AX, FTOUL returns
  4784.         with the carry flag set.
  4785.  
  4786. Include:    stdlib.a
  4787.  
  4788.  
  4789. Routine:  fpadd
  4790. ---------------
  4791.  
  4792. Category:             Floating point Routine
  4793.  
  4794. Registers on entry:   None
  4795.  
  4796. Registers on return:  None
  4797.  
  4798. Flags affected:       None
  4799.  
  4800. Example of Usage:
  4801.             fpadd
  4802.  
  4803. Description:    FPADD adds the floating point operand to the floating point
  4804.         accumulator leaving the result in the floating point
  4805.         accumulator.
  4806.  
  4807. Include:    stdlib.a
  4808.  
  4809.  
  4810. Routine:  fpsub
  4811. ---------------
  4812.  
  4813. Category:             Floating point Routine
  4814.  
  4815. Registers on entry:   None
  4816.  
  4817. Registers on return:  None
  4818.  
  4819. Flags affected:       None
  4820.  
  4821. Example of Usage:
  4822.             fpsub
  4823.  
  4824. Description:    FPSUB subtracts the floating point operand from the floating
  4825.         point accumulator leaving the result in the floating point
  4826.         accumulator.
  4827.  
  4828. Include:    stdlib.a
  4829.  
  4830.  
  4831. Routine:  fpcmp
  4832. ---------------
  4833.  
  4834. Category:             Floating point Routine
  4835.  
  4836. Registers on entry:   None
  4837.  
  4838. Registers on return:  AX contains result of comparison.
  4839.  
  4840. Flags affected:       As appropriate for a comparison.  You can use the
  4841.               conditional branches to check the comparison after
  4842.               calling this routine.  Be sure to use the *signed*
  4843.               conditional jumps (e.g., JG, JGE, etc.).
  4844.  
  4845. Example of Usage:
  4846.             fpcmp
  4847.             jge    FPACCgeFPOP
  4848.  
  4849. Description:    FPCMP compares the floating point accumulator to the
  4850.         floating point operand and sets the flags according to the
  4851.         result of the comparison.  It also returns a value in AX
  4852.         as follows:
  4853.  
  4854.             AX    Result
  4855.             -1    FPACC < FPOP
  4856.              0    FPACC = FPOP
  4857.              1    FPACC > FPOP
  4858.  
  4859. Include:    stdlib.a
  4860.  
  4861.  
  4862. Routine:  fpmul
  4863. --------------
  4864.  
  4865. Category:             Floating point Routine
  4866.  
  4867. Registers on entry:   None
  4868.  
  4869. Registers on return:  None
  4870.  
  4871. Flags affected:       None
  4872.  
  4873. Example of Usage:
  4874.             fpmul
  4875.  
  4876. Description:    FPMUL multiplies the floating point accumulator by the floating
  4877.         point operand and leaves the result in the floating point
  4878.         accumulator.
  4879.  
  4880. Include:    stdlib.a
  4881.  
  4882.  
  4883. Routine:  fpdiv
  4884. ---------------
  4885.  
  4886. Category:             Floating point Routine
  4887.  
  4888. Registers on entry:   None
  4889.  
  4890. Registers on return:  None
  4891.  
  4892. Flags affected:       None
  4893.  
  4894. Example of Usage:
  4895.             fpdiv
  4896.  
  4897. Description:    FPDIV divides the floating point accumulator by the floating
  4898.         point operand and leaves the result in the floating point
  4899.         accumulator.
  4900.  
  4901. Include:    stdlib.a
  4902.  
  4903.  
  4904. Routine:  ftoa (2,m)
  4905. --------------------
  4906.  
  4907. Category:             Floating point Routine
  4908.  
  4909. Registers on entry:   ES:DI points at buffer to hold result (ftoa/ftoa2 only)
  4910.               AL- Field width for floating point value.
  4911.               AH- Number of positions to the right of the dec pt.
  4912.  
  4913. Registers on return:  ES:DI points at beginning of string (ftoa/ftoam only)
  4914.               ES:DI points at zero terminating byte (ftoa2 only)
  4915.  
  4916. Flags affected:       Carry is set if malloc error (ftoam only)
  4917.  
  4918. Example of Usage:
  4919.             mov    di, seg buffer
  4920.             mov    es, di
  4921.             lea    di, buffer
  4922.             mov    ah, 2        ;Two digits after "."
  4923.             mov    al, 10        ;Use a total of ten positions
  4924.             ftoa
  4925.  
  4926.  
  4927.  
  4928. Description:    FTOA (2,M) converts the value in the floating point accumulator
  4929.         to a string of characters which represent that value.  These
  4930.         routines use a decimal representation.  The value in AH is
  4931.         the number of digits to put after the decimal point, AL
  4932.         contains the total field width (including room for the sign
  4933.         and decimal point).  The field width specification works
  4934.         just like Pascal or FORTRAN.  If the number will not fit in
  4935.         the specified field width, FTOA outputs a bunch of "#"
  4936.         characters.
  4937.  
  4938.         FTOA stores the converted string at the address specified by
  4939.         ES:DI upon entry.  There must be at least AL+1 bytes at this
  4940.         address.  It returns with ES:DI pointing at the start of this
  4941.         buffer.
  4942.  
  4943.         FTOA2 works just like FTOA except it does not preserve DI.
  4944.         It returns with DI pointing at the zero terminating byte.
  4945.  
  4946.         FTOAM allocates storage for the string on the heap and returns
  4947.         a pointer to the converted string in ES:DI.
  4948.  
  4949.         Note: this routine preserves the value in the floating point
  4950.         accumulator but it wipes out the value in the floating point
  4951.         operand.
  4952.  
  4953. Include:    stdlib.a
  4954.  
  4955.  
  4956. Routine:  etoa (2,m)
  4957. --------------------
  4958.  
  4959. Category:             Floating point Routine
  4960.  
  4961. Registers on entry:   ES:DI points at buffer to hold result (etoa/etoa2 only)
  4962.               AL- Field width for floating point value.
  4963.  
  4964. Registers on return:  ES:DI points at beginning of string (etoa/etoam only)
  4965.               ES:DI points at zero terminating byte (etoa2 only)
  4966.  
  4967. Flags affected:       Carry is set if malloc error (etoam only)
  4968.  
  4969. Example of Usage:
  4970.             mov    al, 14        ;Use a total of 14 positions
  4971.             etoam
  4972.             puts
  4973.             putcr
  4974.             free
  4975.  
  4976.  
  4977.  
  4978. Description:    ETOA (2,M) converts the value in the floating point accumulator
  4979.         to a string of characters which represent that value.  These
  4980.         routines use an exponential (scientific notation)
  4981.         representation.  AL contains the field width.  It contains
  4982.         the number of print position to use when outputting the
  4983.         number.  The field width specification works just like Pascal
  4984.         or FORTRAN.  If the number will not fit in the specified
  4985.         field width, ETOA outputs a bunch of "#" characters.
  4986.  
  4987.         ETOA stores the converted string at the address specified by
  4988.         ES:DI upon entry.  There must be at least AL+1 bytes at this
  4989.         address.  It returns with ES:DI pointing at the start of this
  4990.         buffer.
  4991.  
  4992.         ETOA2 works just like ETOA except it does not preserve DI.
  4993.         It returns with DI pointing at the zero terminating byte.
  4994.  
  4995.         ETOAM allocates storage for the string on the heap and returns
  4996.         a pointer to the converted string in ES:DI.
  4997.  
  4998.         Note: this routine preserves the value in the floating point
  4999.         accumulator but it wipes out the value in the floating point
  5000.         operand.
  5001.  
  5002. Include:    stdlib.a
  5003.  
  5004.  
  5005. Routine:  atof
  5006. --------------
  5007.  
  5008. Category:             Floating point Routine
  5009.  
  5010. Registers on entry:   ES:DI points at a string containing the representation
  5011.               of a floating point number in ASCII form.
  5012.  
  5013. Registers on return:  None
  5014.  
  5015. Flags affected:       None
  5016.  
  5017. Example of Usage:
  5018.             les    di, FPStr
  5019.             atof
  5020.  
  5021.  
  5022. Description:    ATOF converts the string pointed at by ES:DI into a floating
  5023.         point value and leaves this value in the floating point
  5024.         accumulator.  Legal floating point values are described
  5025.         by the following regular expression:
  5026.  
  5027.  
  5028.         {" "}* {+ | -} ( ([0-9]+ {"." [0-9]*}) | ("." [0-9]+)}
  5029.                 {(e | E) {+ | -} [0-9] {[0-9]*}}
  5030.  
  5031.  "{}" denote optional items.
  5032.  "|"  denotes OR.
  5033.  "()" groups items together.
  5034.  
  5035.  
  5036.  
  5037. Include:    stdlib.a
  5038.  
  5039.  
  5040.  
  5041. ******************************************************************************
  5042.  
  5043.         File I/O Routines
  5044.  
  5045.            Featuring:
  5046.                - Opening and closing files
  5047.                - Creating new files
  5048.                - Deleting files
  5049.                - Renaming files
  5050.                - File "seeking"
  5051.                - Blocked I/O:
  5052.                    - Reading from files using getc
  5053.                    - Writing to files using putc and puts
  5054.                    - File flushing
  5055.  
  5056. ******************************************************************************
  5057.  
  5058.            Written by:
  5059.  
  5060.                Mark Radleigh
  5061.                &
  5062.  
  5063.                Brian Harvey
  5064.  
  5065. ******************************************************************************
  5066.  
  5067.  
  5068. fcreate
  5069. *    Creates a new file.
  5070. *    If a file already exists with the requested name, it will be deleted
  5071.     and a new one will take its place.
  5072. Inputs: ES:DI- Contains address of the filename for the new file
  5073. Outputs: AX- If no error occured in creating the file, it contains a
  5074.         filehandle number assigned to this file by DOS.
  5075.          If an error has occurred, it contains one of the following error
  5076.         codes:
  5077.          3 - Path not found
  5078.          4 - Too many open files
  5079.          5 - Access denied
  5080.      Carry flag- 0 if no error occured, 1 if error
  5081. Include:    Stdlib.a
  5082. Updated:    6/14/91        First public release
  5083.  
  5084. This routine creates a new file on the specified pathname. If no pathname or
  5085. device is specified, the file will be created in the current working directory.
  5086. If the file has been successfully created (No errors occured!), then this
  5087. routine returns in the ax register a number that is the DOS filehandle for
  5088. this file. Don't lose this value. You will need it when to want to close the
  5089. file (using fclose). Save the ax register in a variable after the routine call
  5090. and move the variable back into the ax register before you call the fclose
  5091. stdlib routine. See documentation for fclose for more information.
  5092.  
  5093. FILEHANDLE NOTICE: The filehandle returned in the ax register is not the true
  5094. DOS filehandle for this file. However, this filehandle is too be used when
  5095. calling the file routines in stdlib. In order to get the true filehandle for a
  5096. certain file, see the documentation for the stdlib routine, DOSHandle
  5097.  
  5098. Example:
  5099.  
  5100.         print
  5101.         db      "What do you desire to create?",0
  5102.         gets                            ;Get filename and store in es:di
  5103.         fcreate                      ;Call routine to create file
  5104.         jc      error                   ;If the carry flag is set,
  5105.                         ;an error has occured.
  5106.         mov     fileptr, ax             ;Save the filehandle stored in
  5107.                         ;the ax register for future
  5108.                         ;use
  5109.  
  5110. fopen
  5111. *    Opens a file for reading or writing.
  5112. *    File I/O depends on value in the al register.
  5113. Inputs: ES:DI- Contains address of the filename for the file to be opened
  5114.     AL- Contains 0 if the file is to be opened for reading.
  5115.         Contains 1 if the file is to be opened for writing.
  5116. Outputs: AX- If no error occured in opening the file, it contains a
  5117.         filehandle number assigned to this file by DOS.
  5118.          If an error has occured, it contains one of the following error
  5119.         codes:
  5120.          2 - File not found
  5121.          4 - Too many open files
  5122.          5 - Access denied
  5123.          12 - Invalid access
  5124.      Carry flag- 0 if no error occured, 1 if error
  5125. Include:    Stdlib.a
  5126. Updated:    6/14/91        First public release
  5127.  
  5128. This routine opens a file for reading or writing using the specified filename
  5129. and directory (any standard DOS file pathway) in ES:DI. Using the stdlib gets
  5130. routine is an excellent and advisable way (Not to mention an easy way!) of
  5131. getting the filename in ES:DI. The user must also move one of two values into
  5132. the al register before calling fopen. To open a file for reading, the al
  5133. register must contain the value 0 and to open a file for writing, the al
  5134. register must contain the value 1. If the file has been successfully opened, a
  5135. filehandle for this file assigned by DOS. Save this filehandle in some sort of
  5136. variable so you can move it back into the ax register when you call the stdlib
  5137. routine fclose to close the file. See documentation for fclose for more
  5138. information. Examine the examples below for a suggested way of saving the
  5139. filehandle (the example uses a variable called fileptr, but the name is
  5140. arbritary).
  5141.  
  5142. FILEHANDLE NOTICE: The filehandle returned in the ax register is not the true
  5143. DOS filehandle for this file. However, this filehandle is too be used when
  5144. calling the file routines in stdlib. In order to get the true filehandle for a
  5145. certain file, see the documentation for the stdlib routine, DOSHandle
  5146.  
  5147. NOTICE FOR MULTIPLE OPEN FILES: fopen, along with fcreate and fclose, allows the
  5148.                 user have up to 10 files open at the same time.
  5149.                 In order to keep track of all the filehandles of
  5150.                 these open files, it is suggested that a
  5151.                 separate variable for the filehandle of each
  5152.                 of the open files be used to keep track of the
  5153.                 handles.
  5154.  
  5155. Example for opening mulitple files (same theory applies with fcreate):
  5156.         print
  5157.         db      "What do you desire to open?",0
  5158.         gets                            ;Get filename and store in es:di
  5159.         mov     al, 1                   ;1 so the file will be opened
  5160.                         ;for writing
  5161.         fopen                        ;Call routine to open file
  5162.         jc      error                   ;If the carry flag is set,
  5163.                         ;an error has occured, so quit!
  5164.         mov     fileptr, ax             ;Save the filehandle stored in
  5165.                         ;the ax register for future
  5166.                         ;use
  5167.         print
  5168.         db    "What is the 2nd file you wish to open?",0
  5169.         gets
  5170.         mov    al, 1
  5171.         fopen                ;Open 2nd file for writing
  5172.         jc    error            ;Error??
  5173.         mov    fileptr2,ax        ;Save the filehandle for the 2nd
  5174.                         ;open file in a separate
  5175.                         ;variable
  5176.  
  5177.  
  5178. Warning:  If the file the user wishes to open already exists and the user wants
  5179.       to open it for writing, then the data written to the file will
  5180.       overwrite the pre-exeisting data. See docs for fseek to overcome
  5181.       this problem.
  5182.  
  5183. Example:
  5184.  
  5185. ;Open a file for writing
  5186.         print
  5187.         db      "What do you desire to open?",0
  5188.         gets                            ;Get filename and store in es:di
  5189.         mov    al, 1            ;1 so the file will be opened
  5190.                         ;for writing
  5191.  
  5192.  
  5193.         fopen                        ;Call routine to open file
  5194.         jc      error                   ;If the carry flag is set,
  5195.                         ;an error has occured, so quit!
  5196.         mov     fileptr, ax             ;Save the filehandle stored in
  5197.                         ;the ax register for future
  5198.                         ;use
  5199.  
  5200. ;Open a file for reading
  5201.         print
  5202.         db      "What do you desire to open?",0
  5203.         gets                            ;Get filename and store in es:di
  5204.         mov     al, 0                   ;0 so the file will be opened
  5205.                         ;for reading
  5206.                 fopen                        ;Call routine to open file
  5207.                 jc      error                   ;If the carry flag is set,
  5208.                                                 ;an error has occured, so quit!
  5209.         mov     fileptr, ax             ;Save the filehandle stored in
  5210.                                                 ;the ax register for future
  5211.                                                 ;use
  5212.  
  5213. fclose
  5214. *    Closes an open file
  5215. *    Filehandle for file to be closed needs to be in the ax register
  5216. Input: AX- Contains the filehandle variable of the file to close.
  5217. Outputs: AX- If carry flag is set (error occured), then ax contains an error
  5218.         code.
  5219.          If an error has occured, it contains the following error code:
  5220.         6 - Invalid file handle
  5221.         10 - Trouble with FREE (memory freeing routine)
  5222.      Carry flag- 0 if no error occured, 1 if error.
  5223. Include:    Stdlib.a
  5224. Updated:    6/14/91        First public release
  5225.  
  5226. This routine closes an open file. Once the file is closed no I/O processes
  5227. can be made on the file. Before calling the routine, fclose, the user must
  5228. move into the ax register the filehandle assigned to this file when the file
  5229. was opened or created. The only error that can occur is if the user moved into
  5230. the ax register a filehandle that does not belong to one of the opened files.
  5231. The following example demonstrates how to close a file that was opened in one of
  5232. the fopen examples or the file that was created in the fcreate example, whose
  5233. filehandle was saved in variable called fileptr.
  5234. Example:
  5235.                 mov     ax, fileptr        ;Move the DOS filehandle into
  5236.                         ;the ax register before
  5237.                         ;calling routine
  5238.                 fclose                ;Close the file
  5239.                 cmp     ax, 6            ;If the filehandle was an
  5240.                         ;invalid filehandle jump to
  5241.                         ;user's code for error's
  5242.                 je      error
  5243. ;The following code is a continuation in the case that multiple files are
  5244. ;open. The code close the second open file.
  5245.         mov    ax, fileptr2
  5246.         fclose
  5247.         cmp    ax, 6
  5248.         je    error
  5249.  
  5250. fwriteon
  5251. *    Turns on the write to file mode.
  5252. *    Redirects the ouput of stdlib routines putc and puts to a open file
  5253. Input: AX- Contains the filehandle of which open file to write data to.
  5254. Outputs: AX- If an error occurs in attempting to write to a file, ax will
  5255.         contain one of the following error codes:
  5256.           5 - Accessed denied
  5257.           6 - Invalid handle
  5258.      Carry flag- 0 if no error occured, 1 if error.
  5259. Include:    Stdlib.a
  5260. Updated:    6/14/91        First public release
  5261.  
  5262. This routine turns the write to disk mode on. In other words, it redirects the
  5263. output of the stdlib putc routine so that instead of writing data to the screen,
  5264. the data is written to the file whose filehandle is in the ax register when
  5265. fwriteon is called. The routine that replaces the output device of putc's ouput
  5266. actually uses what is known as Blocked I/O. Instead of writing one character
  5267. to the file each time the user calls getc, each character is stored in a buffer
  5268. in memory. When the buffer contains 256 characters, that buffer is written to
  5269. the file as a block. The buffer is then cleared and more characters can be read
  5270. with getc. Using blocked I/O is a lot faster than one character at a time. Along
  5271. with getc, the stdlib routine gets' ouput is also redirected during fwriteon
  5272. mode, since in the stdlib, gets actually just calls getc many times.
  5273.  
  5274. Example:
  5275. ;This code would appear in a program after a file has been created or opened
  5276. ;for "gets"
  5277.         mov    ax, fileptr        ;Move into ax filehandle of
  5278.                         ;file to write to
  5279.                 fwriteon                     ;Call function to redirect
  5280.                                                 ;the output of putc and puts
  5281.         puts
  5282.         fwriteoff            ;Turn off write to disk mode
  5283.         puts
  5284. ;The puts must appear after the fwriteoff command because gets automatically
  5285. ;writes whatever is in ES:DI to the screen (or in this case the file). The puts
  5286. ;appearing after the writeoff, prints whatever is at ES:DI to the screen. If
  5287. ;the puts were to appear in the writeoon mode, the string at ES:DI would be
  5288. ;written to the file twice
  5289.  
  5290. Example:
  5291. ;This code would appear in a program after a file has been created or opened
  5292. ;for "getc"
  5293.         mov    ax, fileptr        ;Move into ax filehandle of
  5294.                         ;file to write to
  5295.         fwriteon                 ;Call function to redirect
  5296.                         ;the output of putc and puts
  5297.         getc
  5298.         putc
  5299.         fwriteoff
  5300. ;Unlike in the previous example, getc and putc may both appear in the writeon
  5301. ;mode. The getc will get a character from the keyboard and store it in the al
  5302. ;register. Putc will then write whatever is in the al register to the
  5303. ;specified open file. In order for the user to see what character they typed
  5304. ;in, in the previous example, a putc should appear after the fwriteoff call.
  5305. ;Since fwriteoff redirects the putc ouput back to normal (See docs for fwriteoff
  5306. ;for more info) the character in al will be put on the screen.
  5307.  
  5308. fwriteoff
  5309. *    Turns off the write to file mode
  5310. *    Redirects the output of putc back to normal (the screen!)
  5311.         mode.
  5312. Include:    Stdlib.a
  5313. Updated:    6/14/91        First public release
  5314.  
  5315. This routines changes or redirects the ouput of stdlib's putc back to normal.
  5316. In other words, since the routine fwriteon made the ouput go to a disk file,
  5317. changing it back to normal means that after this routine is called, all putc's
  5318. used will print whatever is in the al register to the screen.
  5319.  
  5320. Example:
  5321. ;This example gets a character from the keyboard, prints to a disk file and then
  5322. ;prints to the screen the character in the al register that was entered.
  5323.         mov    ax, fileptr        ;Move into ax filehandle of
  5324.                         ;file to write to
  5325.         fwriteon                 ;Call function to redirect
  5326.                         ;the output of putc and puts
  5327.         getc                ;Get character and store in al
  5328.         putc                ;Print character in al to file
  5329.         fwriteoff            ;Change ouput of putc back to
  5330.                         ;normal
  5331.         putc                ;Prints character in al to
  5332.                         ;screen
  5333. fflush
  5334. *    Flushes the buffer in an opened write file to that file
  5335. Inputs:    AX- Contains Stdlib filehandle of file whose buffer is to be flushed
  5336. Outputs: None.
  5337. Include:    Stdlib.a
  5338. Updated:        6/14/91         First public release
  5339.  
  5340. This routine takes all data from the buffer associated with the Stdlib
  5341. filehandle passed in AX and writes it to the file. It then clears the buffer.
  5342. NOTE: This routine is automatically called on by Fclose.
  5343.  
  5344. freadon
  5345. *    Turns on the read from file mode
  5346. *    Changes the source of the input for the stdlib function getc
  5347. Input:    AX- Contains the filehandle of which open file to read data from.
  5348. Output: AL- Contains a character read from the specified file.
  5349.     AX- If an error occurs in attempting to read from a file, ax will
  5350.         contain one of the following error codes:
  5351.           5 - Access denied
  5352.           6 - Invalid handle
  5353.           8 - EOF
  5354.     Carry flag- 0 if no error occured, 1 if error.
  5355. Include:    Stdlib.a
  5356. Updated:    6/14/91        First public release
  5357.  
  5358. This routine turns the read from file mode on. It redirects the source from
  5359. which stdlib's getc routine gets its "character" from. Instead of getting the
  5360. character from the keyboard, the redirected getc reads a character from a opened
  5361. file. Actually, this routine uses the blocked I/O idea discussed in the writeon
  5362. documentation. This routine when called for the first time, meaning the buffer
  5363. for the current file to be read from is clear, will read it 256 characters from
  5364. (If there is that many) a file and store it in the buffer. The first character
  5365. in the buffer is then put in the al register for the user to then use for
  5366. whatever they wish. The next time the user calls getc (without calling the
  5367. freadoff rotuine yet) the next character in the buffer will be stored in the al
  5368. register. When the buffer is empty, another 256 bytes will be read into it. When
  5369. the routine freadoff is called, any getc routines called after that will get
  5370. a character from the keyboard.
  5371.  
  5372. Example:
  5373.         mov    ax, fileptr        ;Move the filehandle of the
  5374.                         ;file to read from into ax
  5375.         freadon                ;Turn on read mode!
  5376.         mov    cx, 10            ;Set up loop to read 10
  5377.                         ;characters from a file and
  5378.                         ;print them to the screen
  5379. loop1:        getc                ;Get character from buffer and
  5380.                         ;store in al
  5381.         jc    error            ;If error in reading from file
  5382.                         ;jump to user's code for
  5383.                         ;handling code
  5384.         putc                ;Print character in al to the
  5385.                         ;screen
  5386.         loop    loop1
  5387.         freadoff            ;turn read mode off from this
  5388.                         ;file
  5389.  
  5390. freadoff
  5391. *    Turns off the read from file mode
  5392. *    Redirects the source of the data for stdlib's getc routine back to
  5393.     normal
  5394.  
  5395. This routine changes the source from which stdlib's getc routine gets its
  5396. "character" from back to normal. After calling this routine, instead of reading
  5397. characters from the disk, using blocked I/O, the getc routine will get
  5398. it's "character" from the keyboard.
  5399.  
  5400. For code example of how to use freadoff, see the example of code above for
  5401. freadon.
  5402.  
  5403.  
  5404. fseek
  5405. *    Moves the file pointer of a file to anywhere in the file
  5406. Inputs:    SI- Contains the filehandle variable of the file to be used, or "seeked"
  5407.     AL- Contains the offset from where to start the file seeking.
  5408.         0 - Seek from the begining of the file.
  5409.         1 - Seek from current pointer position
  5410.         2 - Seek backwards from the end of file
  5411.     CX:DX- Distance to move in file, in bytes.
  5412. Outputs: DX:AX- Contains the new file position if no error
  5413.      AX- One of the following error codes if an error occured while
  5414.         "seeking":
  5415.           1 - Invalid function
  5416.           6 - Invalid handle
  5417.     Carry flag- 0 if no error occured, 1 if error.
  5418. Include:    Stdlib.a
  5419. Updated:    6/14/91        First public release
  5420.  
  5421. This routine allows the user the move the file pointer to any position within
  5422. a file. You can not move backwards in a file by having a negative value in
  5423. CX:DX. The value in CX:DX must be an unsigned integer. 
  5424.  
  5425. Example:
  5426.         mov    si, fileptr        ;Move the filehandle of the
  5427.                         ;file to be seeked
  5428.         mov    al, 0            ;Start moving pointer from
  5429.                         ;beginning of file
  5430.         xor    cx, cx            ;Clear the cx register
  5431.         mov    dx, 10            ;Move file pointer 10 bytes
  5432.                         ;into file
  5433.         fseek                ;Seek!!!
  5434.         jc    error            ;Jump to error code if error
  5435.  
  5436. To find out where the file pointer currently is in the file, first xor cx and 
  5437. dx registers and call fseek. It will return in DX:AX the file pointer's
  5438. position.
  5439.         mov    si, fileptr        ;Move the filehandle of the
  5440.                         ;file to be seeked
  5441.         mov    al, 1            ;Start moving pointer from
  5442.                         ;the current position
  5443.         xor    cx, cx            ;Clear the cx register
  5444.         xor    dx, dx            ;Clear the dx register
  5445.         fseek                ;Seek!!!
  5446.         jc    error            ;Jump to error code if error
  5447.                         ;else DX:AX contains the current
  5448.                         ;File pointer position.
  5449.  
  5450.  
  5451. DOSHandle
  5452. *    Returns in the ax register the true DOS filehandle for a file
  5453. Input:    AX- Contains the filehandle for the file given to the user from
  5454.         stdlib routine, fopen or fcreate
  5455. Ouputs:    AX- Contains the true filehandle given to the requested file by DOS
  5456.     AX- If an error occured, it contains the following error code:
  5457.           1 - Invalid pseudo-filehandle
  5458.     Carry flag- 0 if no error occured, 1 if error.
  5459. Include:    Stdlib.a
  5460. Updated:    6/14/91        First public release
  5461.  
  5462. This routine returns in the ax register the true filehandle variable given by
  5463. DOS for a particular file. The filehandle returned when calling the stdlib
  5464. functions, fcreate and fopen, is not the true filehandle for the file used
  5465. in those routines. The value returned is a value created by the routines, which
  5466. stores the filehandles for multiple files in a structure in memory. The value
  5467. returned from those functions is actually the index into the structure to the
  5468. real filehandle for the file. This function, DOSHandle, returns from this
  5469. structure in memory the actual filehandle for a file that has been opened. 
  5470. NOTICE: This routine is only useful to those who need to know the real
  5471. filehandle of a file that has been created or opened with fopen or fcreate. For
  5472. those who will only be using the File I/O routines provided in stdlib then
  5473. this routine will be of no importance. It is provided only for advanced assembly
  5474. language programmers who with to do other things with files and need to know
  5475. their real filehandle values.
  5476.  
  5477. Example:
  5478.         mov    ax, fileptr        ;Move into ax the filehandle
  5479.                         ;given to the user file fopen
  5480.                         ;or fcreate
  5481.         DOSHandle            ;Get the true filehandle for
  5482.                         ;a file and store it in the
  5483.                         ;ax register
  5484.         mov    truehandle, ax
  5485.  
  5486. frename
  5487. *    Renames a file
  5488. Input:    DX:SI- Contains the original pathname of the file
  5489.     ES:DI- Contains the new pathname of the file
  5490. Ouputs:    AX- Contains one of the following error codes if an error occured:
  5491.           2 - File not found
  5492.           5 - Access denied
  5493.           17 - Not the same device
  5494.     Carry flag- 0 if no error occured, 1 if error.
  5495. Include:    Stdlib.a
  5496. Updated:    6/14/91        First public release
  5497.  
  5498. This routine renames the file whose name appears in a string at DX:SI with the
  5499. name that appears at the string pointed at by ES:DI. If an error occurs, then
  5500. an appropriate error code appears in the ax register.
  5501.  
  5502. Example:
  5503.         print
  5504.         db    "Enter the source filename: ",0
  5505.         gets
  5506.         mov    dx, es
  5507.         mov    si, di
  5508.         print
  5509.         db    cr, lf, "Enter the new filename: ",0
  5510.         gets
  5511.         frename
  5512.         jc    error
  5513.  
  5514. fdel
  5515. *    Deletes a file
  5516. Input: ES:DI- Contains the address of zero terminated pathname of file
  5517. Output: AX- Contains one of the following error codes if an error occured:
  5518.           2 - File not found
  5519.           5 - Access denied
  5520.         Carry flag- 0 if no error occured, 1 if error.
  5521. Include:        Stdlib.a
  5522. Updated:        6/14/91         First public release
  5523.  
  5524. This routine deletes the filename that is in the string that ES:DI points to.
  5525.  
  5526. Example:
  5527.         print
  5528.         db    "Name of file to delete?",0
  5529.         gets
  5530.         fdel                ;Delete the file!
  5531.         jc    error            ;Jump to error code if an error
  5532.  
  5533.  
  5534.  
  5535.  
  5536. ======================
  5537. Miscellaneous Routines
  5538. ======================
  5539.  
  5540. This routines either defy categorization, or they haven't been properly
  5541. organized yet.
  5542.  
  5543. Mostly (like the rest of this library) they have simply been stuck here
  5544. until somebody gets the time to reorganize *everything*.
  5545.  
  5546.  
  5547.  
  5548.  
  5549. Routine:  Random
  5550. ----------------
  5551.  
  5552. Author:              Unknown.  Copied off a file on one of the networks,
  5553.               tweaked, and added to the library.  Any info on the
  5554.               original author would be appreciated.
  5555.  
  5556. Category:             Miscellaneous
  5557.  
  5558. Registers on entry:   None
  5559.  
  5560. Registers on return:  AX-    Contains random number
  5561.  
  5562. Flags affected:       None
  5563.  
  5564. Example of Usage:
  5565.             random    ;Generate random number in AX
  5566.             puti    ;Print the random number.
  5567.  
  5568.  
  5569. Description:    
  5570.  
  5571.  This routine computes a 16-bit random number each time you call it.  It
  5572. returns the random number in the AX register.  You may treat this as a signed
  5573. or unsigned value as it utilizes all 16 bits.  This code uses an internal
  5574. table of seed values.  If you are interested in producing repeatable sequences
  5575. of random numbers, please look at the source listings for this file.
  5576.  
  5577.  If you are interested in producing truly random values (well, closer than you
  5578. will get from this code by calling it right off the bat) look at the randomize
  5579. routine which tweaks the seed table based on the current time of day clock
  5580. value.
  5581.  
  5582. Include:    stdlib.a
  5583.  
  5584.  
  5585. Routine:  Randomize
  5586. -------------------
  5587.  
  5588. Author:              Unknown.  Copied off a file on one of the networks,
  5589.               tweaked, and added to the library.  Any info on the
  5590.               original author would be appreciated.
  5591.  
  5592. Category:             Miscellaneous
  5593.  
  5594. Registers on entry:   None
  5595.  
  5596. Registers on return:  None
  5597.  
  5598. Flags affected:       None
  5599.  
  5600. Example of Usage:
  5601.             randomize    ;Randomize the seeds.
  5602.             random        ;Get a brand new random number
  5603.             puti        ;Print it
  5604.  
  5605. Description:    
  5606.  
  5607. Random's internal seed table is hard coded.  It was designed to produce a
  5608. sequence of random numbers with a very long period.  However, each time you
  5609. run a program using Random, it will generate the exact same sequence of
  5610. random numbers.  This could be distressing, for example, in a game where
  5611. after a while the player(s) could memorize some sequence of events based
  5612. on the random number generator.
  5613.  
  5614.  Randomize uses the time of day clock value to scramble the internal random
  5615. seed table.  If you call randomize before using random the first time, you
  5616. will generally get a different sequence of random numbers each time you
  5617. run the program.
  5618.  
  5619.  Note that it is dangerous to call randomize more than once inside any program.
  5620. The time of day clock is not a random source when invoked fairly often.
  5621. Furthermore, once the seeds are randomized, random does a pretty good job of
  5622. randomizing the results.
  5623.  
  5624. Include:    stdlib.a
  5625.  
  5626.  
  5627. Routine:  cpuid
  5628. ---------------
  5629.  
  5630. Author:              Original implementation was supplied by Intel Corp.
  5631.               Various modifications were made for inclusion into
  5632.               the UCR Standard Library.
  5633.  
  5634. Category:             Miscellaneous
  5635.  
  5636. Registers on entry:   None
  5637.  
  5638. Registers on return:  AX-    Contains processor ID (86, 286, 386, or
  5639.                 486.  Note 8088=86).
  5640.  
  5641.               BX-    Contains coprocessor ID (87, 286, 387,
  5642.                 or 487).  Note that a true 486 will have
  5643.                 an 80487 built-in, 486sx chips, however, will
  5644.                 not.
  5645.  
  5646. Flags affected:       None
  5647.  
  5648. Example of Usage:
  5649.             cpuid
  5650.             cmp    ax, 8086    ;Is this an 8086?
  5651.  
  5652. Description:    
  5653.  
  5654.  For those programs which absolutely need to know the CPU in use, CPUID does
  5655. a reasonable job (in DOS real mode) of figuring this out for you.  As with
  5656. all CPU identification routines, there are bound to be some problems with this
  5657. one when operating in protected mode. But for normal DOS applications it
  5658. appears to work great.  This routine came straight from the horse's mouth
  5659. (Intel Corporation) so you can place a little more faith in it than most that
  5660. are floating around.  Intel's blessing doesn't guarantee that this routine
  5661. is perfect, though; always keep that in mind.
  5662.  
  5663. Include:    stdlib.a
  5664.  
  5665.  
  5666. ===================
  5667. SmartArray Routines
  5668. ===================
  5669.  
  5670.   The SmartArray routines provide a consistent and easy to master interface to
  5671. vectors, matrices, and higher-dimension arrays.  It is a weak attempt at an
  5672. abstract, encapsulated, array data type (weak because the internal structure
  5673. is still visible, indeed, intended to be visible, to the main program).  These
  5674. routines include many operations stolen from the APL programming language.  As
  5675. such, they comprise a powerful set of matrix operations.  On the other hand,
  5676. because of their generality, they do not perform as quickly as hand-optimized
  5677. code doing the same thing.  These routines definitely represent a trade-off
  5678. between ease of use and performance.  That is not to say that these routines
  5679. are all slow.  Some operations, like matrix multiplication, are so slow that
  5680. the overhead of dealing with arrays in this fashion pales in comparison.
  5681. For other operations (e.g., extracting an element of an array), the overhead
  5682. required may far exceed the actual work performed.  This is why these routines
  5683. do provide access to the internal data structures.
  5684.  
  5685. The array access routines come in two basic groups: general array access and
  5686. array operations.  The general array access routines let you allocate arrays,
  5687. access arrays, initialize arrays, and copy arrays.  The array operation
  5688. routines let you perform high-level operations on the arrays.
  5689.  
  5690. SmartArrays are described by a descriptor (also called a "dope vector").  This
  5691. descriptor uses the following data structure:
  5692.  
  5693.     DopeVector    struc
  5694.     ArrayData    dd    ?
  5695.     SizeInBytes    dw    ?
  5696.     ElementSize    dw    ?
  5697.     ArrayType    db    ?
  5698.     NumDimensions    db    ?
  5699.     DimensionList    dw    ?    ;One word for each dimension
  5700.     DopeVector    ends
  5701.  
  5702. The first double word is a pointer to the actual array data.  This is typically
  5703. (though not necessarily) allocated somewhere on the heap with malloc.  The
  5704. SmartArrays package stores all multi-dimensional arrays in row major order.
  5705.  
  5706. The second field above, SizeInBytes, gives the total size of the array data.
  5707. The SmartArray routines use this field for block copies and other operations
  5708. where it's nice to know the actual size of the array, in bytes.  Although
  5709. SmartArrays are typically allocated on the heap, there is no guarantee of this.
  5710. In particular, the SmartArray routines make no assumptions about free bytes
  5711. immediately following the array's data.  The SmartArray routines only
  5712. manipulate the specified number of bytes when treating the array as a whole.
  5713.  
  5714. The ElementSize field gives the number of bytes per array element.  Any value
  5715. may go here, but the SmartArrays package handles 1, 2, 4, 8, and 10 byte
  5716. elements best (especially 1, 2, and 4 byte element sizes).  Since most arrays
  5717. use one of these sizes, you're in great shape.
  5718.  
  5719. The ArrayType field holds the current data type for each element of the array.
  5720.  
  5721. The NumDimensions field is an small integer which gives the number of dimen-
  5722. sions in this array.
  5723.  
  5724. The DimensionList is an array (despite its declaration) containing the number
  5725. of elements specified in the NumDimensions field.  Each entry is a word giving
  5726. the number of array elements in that dimension.
  5727.  
  5728.  
  5729. The following array element type values are currently defined:
  5730.  
  5731.     0-    Untyped element.  Matches any other type.  Defaults to unsigned
  5732.         integer if the type cannot be otherwise determined.
  5733.     1-    Character
  5734.     2-    Boolean
  5735.     3-    Unsigned integer
  5736.     4-    Signed integer
  5737.     5-    Floating point
  5738.     6-    Character String
  5739.     7-    SmartArray Dope Vector
  5740.     8-63    Reserved for future use
  5741.     64-127    User-defined types
  5742.     128-    Pointer to untype element
  5743.     129-    Pointer to character
  5744.     130-    Pointer to boolean
  5745.     131-    Pointer to unsigned integer
  5746.     132-    Pointer to signed integer
  5747.     133-    Pointer to floating point
  5748.     134-    Pointer to character string
  5749.     135-    Pointer to SmartArray Dope Vector
  5750.     136-192    Reserved pointers
  5751.     192-255    Pointers to user-defined types
  5752.  
  5753. The following equates appear in the stdlib.a (& stdlib6.a) equates file:
  5754.  
  5755. SA_untyped    =    0
  5756. SA_char        =    1
  5757. SA_boolean    =    2
  5758. SA_unsigned    =    3
  5759. SA_integer    =    4
  5760. SA_float    =    5
  5761. SA_string    =    6
  5762. SA_dv        =    7
  5763.  
  5764. SAp_untyped    =    80h
  5765. SAp_char    =    81h
  5766. SAp_boolean    =    82h
  5767. SAp_unsigned    =    83h
  5768. SAp_integer    =    84h
  5769. SAp_float    =    85h
  5770. SAp_string    =    86h
  5771. SAp_dv        =    87h
  5772.  
  5773. Note that there are two components to an element's type- the actual type field
  5774. described above and the element size field.  These fields must be consistent.
  5775. The SmartArrays package allows the following combinations:
  5776.  
  5777. Type    Size        Description
  5778. ----    ----        -------------------------------------------------------
  5779.  
  5780.  0    >=1        Untyped data can be any size.
  5781.  1     1        Character type must be one byte long or an error occurs
  5782.  2     1        Boolean type must be one byte long or an error occurs
  5783.  3    1,2,4        Unsigned integers must be 1, 2, or 4 bytes long.
  5784.  4    1,2,4        Signed integers must be 1, 2, or 4 bytes long.
  5785.  5    4, 8, 10    Floating point values must be 4, 8, or 10 bytes long.
  5786.  6    >=1        Strings can be any size
  5787.  7    >= sizeof dv    Dope vectors have a minimum size, but not a maximum.
  5788.  
  5789. >=80h     4        All pointers are four bytes long.
  5790.  
  5791. The SmartArrays package currently ignores all other types.
  5792.  
  5793. Note that the SmartArrays package is *strongly typed*.  It will refuse, for
  5794. example, to add the elements of a boolean array to an unsigned integer array.
  5795. Except for untype arrays, you are not allowed to mix types in an operation.
  5796. Affected routines return an error code should a type mismatch occur.  If you
  5797. prefer, you can force the SmartArrays package to abort with an error message
  5798. by defining the "AryErrorAbort" symbol prior to including the stdlib.a (or
  5799. stdlib6.a) file.
  5800.  
  5801. The SmartArrays package current defines the following error codes (which also
  5802. appear as equates in the stdlib.a/stdlib6.a files):
  5803.  
  5804. AryNoError    =    0            ;Should never occur
  5805. AryTypeMismatch    =    1            ;Array type mismatch
  5806. AryOverflow    =    2            ;Arithmetic overflow
  5807. AryDiv0        =    3            ;Division by zero
  5808. AryIllegalOp    =    4            ;Illegal operation on array
  5809. AryBounds    =    5            ;Array index error
  5810. AryMemory    =    6            ;Memory allocation error
  5811. AryBadDV    =    7            ;Illegal dope vector
  5812. AryNull        =    8            ;Null pointer to array data
  5813.  
  5814.  
  5815. If an error occurs, the SmartArray routines return with the carry set and
  5816. the error code in AX.  If no error occurs, then the SmartArray routines return
  5817. with the carry flag clear.  This is assuming that you have *not* defined the
  5818. "AryErrorAbort" symbol before the "include stdlib.a" statement in your program.
  5819. If you define the "AryErrorAbort" symbol before the include, the calls to the
  5820. SmartArray routines emit some additional code which checks for any errors.  If
  5821. an error occurs in this case, the system will print an appropriate error
  5822. message and abort the program.
  5823.  
  5824. In addition to the array dope vector structure, the stdlib.a/stdlib6.a files
  5825. also contain a macro for declaring SmartArrays within your program.  Although
  5826. it is perfectly possible to allocate dope vectors on the heap (and, indeed,
  5827. this is a common occurrence), more often than not it is possible to allocate
  5828. the dope vectors, and even the array data, in your data segment.  The
  5829. SmartArrays package provides a macro, "array", to specifically aid in this
  5830. task.  The array macro takes the following parameters:
  5831.  
  5832.     array    name, element_size, type, dimension_list, opt_initial_values
  5833.  
  5834. The name is the label you wish to attach to this smart array data structure.
  5835. This must be a valid assembly language symbol.  Note that the symbol must
  5836. *not* appear in the normal label field.  The macro does the processing of this
  5837. label and it must appear as a parameter to the macro.
  5838.  
  5839. The element_size parameter must be an integer value which is the number of
  5840. bytes to allocate for each array element.
  5841.  
  5842. The type parameter specifies the type of each array element.  If the element
  5843. size and type parameters are incompatible, the array macro will generate an
  5844. assembly time error.
  5845.  
  5846. The dimension_list parameter is a list of numbers, separated by commas and
  5847. surrounded by "<" and ">" which list the number of elements in each array
  5848. dimension.  This list must not be empty and none of the dimension values should
  5849. be zero.
  5850.  
  5851. The optional initial values is another list of values surrounded by "<" and
  5852. ">".  This parameter is optional and need not be present.  If absent, the
  5853. array macro generates a dope vector *only*.  It initializes the array data
  5854. pointer field to NULL.  If there are values present in the initial values
  5855. list, the array macro will allocate storage for the array immediately following
  5856. the dope vector and initializes the array elements to the value(s) in the
  5857. initial value list.  If there are too many items in the initial values list,
  5858. the array macro ignores the extra values.  If there are too few items, the
  5859. array macro reuses the values from the beginning of the list (over and over
  5860. again, if necessary).
  5861.  
  5862. Some examples (no initial values):
  5863.  
  5864.  
  5865. a1:array [0..1,0..1] of integer2; 
  5866.  
  5867.     array    a1, 2, SA_integer, <2,2>
  5868.  
  5869.  
  5870. a2:array [0..7] of unsigned4;
  5871.  
  5872.     array    a2, 4, SA_unsigned, <8>
  5873.  
  5874. a3:array [0..3,0..3,0..3] of real8;
  5875.  
  5876.     array    a3, 8, SA_float, <4,4,4>
  5877.  
  5878.  
  5879. Some examples with initial values:
  5880.  
  5881.     array    b1, 2, SA_integer, <4>, <1,2,3,4>
  5882.  
  5883.     array    b2, 2, SA_unsigned, <3>, <1,2,3,4>    ;ignores "4"
  5884.  
  5885.     array    b3, 2, SA_unsigned, <4>, <1,2,3>    ;Generates 1,2,3,1
  5886.  
  5887.     array    b4, 2, SA_unsigned, <4,4>, <1,0,0,0,0>
  5888.  
  5889. The last example generates the following identity matrix:
  5890.  
  5891.         1 0 0 0
  5892.         0 1 0 0
  5893.         0 0 1 0
  5894.         0 0 0 1
  5895.  
  5896. The array macro reuses initial values once it exhausts the list.  It also fills
  5897. the array in row-major order (that is, it fills up the array a row at a time).
  5898. Since each row in b4 is four bytes long and the initial values list contains
  5899. five bytes, the first pass through the initial values list creates the follow-
  5900. ing:
  5901.  
  5902.         1 0 0 0
  5903.         0 x x x
  5904.         x x x x
  5905.         x x x x
  5906.  
  5907. Since the initialization is not complete, the second pass through the initial
  5908. values list generates:
  5909.  
  5910.         1 0 0 0
  5911.         0 1 0 0
  5912.         0 0 x x
  5913.         x x x x
  5914.  
  5915. and so on.  It is important to note that the array macro ignores row/column
  5916. boundaries while initializing the array.  Array simply treats each array as
  5917. a one-dimensional object during initialization.
  5918.  
  5919. The array routines themselves come in three basic forms: general array manip-
  5920. ulation routines which operate on arrays of any size or dimension, vector
  5921. operations which operate only on single dimension arrays, and matrix operations
  5922. which operate on two-dimensional arrays.  General array operations typically
  5923. begin with the letters "Ary", vector operations usually begin with "vect", and
  5924. matrix routines usually begin with the letters "Mat".  All of these routines,
  5925. despite their name, belong to the SmartArrays package.
  5926.  
  5927.  
  5928. Routine:  AryDVCpy (l)
  5929. ----------------------
  5930.  
  5931. Category:        SmartArray
  5932.  
  5933. Registers on entry:    ES:DI    Points at a SmartArray Dope Vector (DV)
  5934.                 (AryDVCpy only).
  5935.             CS:IP    Points at a SmartArray DV (AryDVCpyl only).
  5936.  
  5937. Registers on return:    ES:DI    Points at a new SmartArray DV on the heap.
  5938.             AH    Error code (only if error occurs).
  5939.  
  5940. Flags affected:        Carry    Error if set.
  5941.  
  5942. Possible errors:    AryMemory
  5943.             AryBounds
  5944.             AryBadDV
  5945.  
  5946. Example of Usage:
  5947.             les    di, array1
  5948.             AryDVCpy
  5949.             mov    word ptr array1too, di
  5950.             mov    word ptr array1too+2, es
  5951.              .
  5952.              .
  5953.              .
  5954.             AryDVCpyl
  5955.             DopeVector <NULL,100,2,sa_unsigned,1,50>
  5956.              .
  5957.              .
  5958.              .
  5959.             AryDVCpyl
  5960.             DopeVector <NULL,100,2,sa_unsigned,2,25>
  5961.             dw       2
  5962.  
  5963. Description:    
  5964.  
  5965.   AryDVCpy duplicates an array dope vector.  It allocates storage on the heap
  5966. for the dope vector and copies the data from the source dope vector to the
  5967. new dope vector.  Note that this does not duplicate the array data.  The
  5968. data pointer in both DVs wind up pointing at the same array data.
  5969.  
  5970.   This routine is mostly useful for generating different "views" of the same
  5971. array.  For example, you could view an array as a vector, matrix, and (possibly)
  5972. higher dimension array all at the same time by making duplicates of the dope
  5973. vector and tweaking the array dimension information.
  5974.  
  5975.   AryDVCpyl gets its dope vector information from the code stream.  The bytes
  5976. which immediately follow the call must be a dope vector structure (including
  5977. any necessary array bounds values).  Note that the number of dimension values
  5978. must exactly match the NumDimensions value.  Since the DopeVector structure
  5979. only provides room for one array bounds values, you must follow the DopeVector
  5980. structure with additional word values if your array has more than one dimension
  5981. (see the second AryDVCpyl example above).
  5982.  
  5983. include: stdlib.a
  5984.  
  5985.  
  5986. Routine:  AryDVCreate
  5987. ---------------------
  5988.  
  5989. Category:        SmartArray
  5990.  
  5991. Registers on entry:    AL    Contains the number of dimensions for this
  5992.                 array.
  5993.  
  5994. Registers on return:    ES:DI    Points at a new SmartArray DV on the heap.
  5995.             AH    Error code (only if error occurs).
  5996.  
  5997. Flags affected:        Carry    Error if set.
  5998.  
  5999. Possible errors:    AryMemory
  6000.  
  6001. Example of Usage:
  6002.             mov    al, 3        ;Create a 3-D array.
  6003.             AryDVCreate
  6004.             mov    word ptr MewArray, di
  6005.             mov    word ptr NewArray+2, es
  6006.  
  6007. Description:    
  6008.  
  6009.   AryDVCreate creates an empty dope vector on the heap and returns a point
  6010. in ES:DI.  All fields are initialized to zero and must be set to something
  6011. else before actually using the array.
  6012.  
  6013. include: stdlib.a
  6014.  
  6015.  
  6016. Routine:  AryAlloc
  6017. ------------------
  6018.  
  6019. Category:        SmartArray
  6020.  
  6021. Registers on entry:    ES:DI    Points at a SmartArray Dope Vector (DV)
  6022.  
  6023. Registers on return:    AH    Error code (only if error occurs).
  6024.  
  6025. Flags affected:        Carry    Error if set.
  6026.  
  6027. Possible errors:    AryMemory
  6028.             AryBadDV
  6029.  
  6030. Example of Usage:
  6031.             les    di, DVPtr
  6032.             AryAlloc
  6033.             jc    Error
  6034.  
  6035. Description:    
  6036.  
  6037.   On entry, ES:DI points at a SmartArray dope vector.  This routine goes in
  6038. and deallocates the array the DV points at (if any, and if it's on the heap),
  6039. allocates sufficient storage for the array on the heap, and stores the pointer
  6040. to the array into the pointer field of the DV.  Note that this routine returns
  6041. ES:DI still pointing at the DV, not the allocated array.
  6042.  
  6043. include: stdlib.a
  6044.  
  6045.  
  6046. Routine:  AryCpy
  6047. ----------------
  6048.  
  6049. Category:        SmartArray
  6050.  
  6051. Registers on entry:    ES:DI    Points at a SmartArray DV (source)
  6052.             DX:SI    Points at a SmartArray DV (dest)
  6053.  
  6054. Registers on return:    AH    Error code (only if error occurs).
  6055.  
  6056. Flags affected:        Carry    Error if set.
  6057.  
  6058. Possible errors:    AryMemory
  6059.             AryBounds
  6060.             AryBadDV
  6061.             AryNull
  6062.             AryTypeMismatch            
  6063.  
  6064. Example of Usage:
  6065.             les    di, DVPtr
  6066.             mov    dx, DV2Ptr+2
  6067.             mov    si, DV2Ptr
  6068.             AryCpy
  6069.             jc    Error
  6070.  
  6071. Description:    
  6072.  
  6073.   AryCpy copies the data from one array to another.  ES:DI points at the DV of
  6074. the source array, DX:SI points at the DV of the destination array.  AryCpy
  6075. first checks to see if the two DVs are compatible (their types, sizes, and
  6076. shapes must be the same).  If not, AryCpy returns with an error.  There is
  6077. one exception: if the element size, type, and bounds fields all contain zeros,
  6078. AryCpy will fill in the appropriate values.  The NumDimensions field must be
  6079. non-zero and must match or the AryCpy routine will return an error.
  6080.  
  6081.   Note that AryCpy does *not* deallocate the array storage associated with
  6082. the destination DV.  If it points at array data on the heap you want to dispose
  6083. of, you must free that storage before calling AryCpy.  The reason is simple:
  6084. the destination DV might not be the only DV pointing at the array data. Freeing
  6085. it up could create some problems.
  6086.  
  6087. include: stdlib.a
  6088.  
  6089.  
  6090. Routine:  AryDup
  6091. ----------------
  6092.  
  6093. Category:        SmartArray
  6094.  
  6095. Registers on entry:    ES:DI    Points at a SmartArray DV (source)
  6096.  
  6097. Registers on return:    ES:DI    Points at new SmartArray DV
  6098.             AH    Error code (only if error occurs).
  6099.  
  6100. Flags affected:        Carry    Error if set.
  6101.  
  6102. Possible errors:    AryMemory
  6103.             AryBadDV
  6104.             AryNull
  6105.  
  6106. Example of Usage:
  6107.             les    di, DVPtr
  6108.             AryDup
  6109.             jc    Error
  6110.  
  6111. Description:    
  6112.  
  6113.   AryDup duplicates an array.  It makes a copy of the dope vector that ES:DI
  6114. points at and it also duplicates the array data on the heap.  It returns a
  6115. pointer to the new dope vector in ES:DI.
  6116.  
  6117. include: stdlib.a
  6118.  
  6119.  
  6120. Routine:  AryCmp
  6121. ----------------
  6122.  
  6123. Category:        SmartArray
  6124.  
  6125. Registers on entry:    ES:DI    Points at a SmartArray DV (source)
  6126.             DX:SI    Points at DV of array to compare against.
  6127.  
  6128. Registers on return:    AL    -1, 0, 1 (for <, =, >)
  6129.             AH    Error code (only if error occurs)
  6130.  
  6131. Flags affected:        O,S,Z    Result of comparison (use signed comparisons)
  6132.             Carry    Set if error occurs (carry is not used to test
  6133.                 the result of the comparison.
  6134.  
  6135. Possible errors:    AryBadDV
  6136.             AryNull
  6137.             AryTypeMismatch            
  6138.  
  6139. Example of Usage:
  6140.             les    di, DVPtr
  6141.             mov    dx, word ptr DV2Ptr2
  6142.             mov    si, word ptr DV2Ptr
  6143.             AryCmp
  6144.             jc    Error
  6145.             jg    ItsBigger
  6146.  
  6147. Description:    
  6148.  
  6149.   AryCmp compares the array specified by ES:DI to the array specified by
  6150. DX:SI.  It returns the result of the comparison in the AL register and in
  6151. the flags (the flags are set for a signed comparison, so use je, jne, jg, jge,
  6152. jl, and jle to test the result).  As usual the carry flag (which isn't used
  6153. for signed comparisons) contains the error status.  If the arrays are not
  6154. the same type, size, and shape this code treats the arrays in not equal and
  6155. returns a type mismatch error code.  If one of the arrays is untyped, the
  6156. code will assume that the arrays are comparable and ignore everything else
  6157. (including size and shape).
  6158.  
  6159.  
  6160. include: stdlib.a
  6161.  
  6162.  
  6163. Routine:  AryClr
  6164. ----------------
  6165.  
  6166. Category:        SmartArray
  6167.  
  6168. Registers on entry:    ES:DI    Points at a SmartArray DV (source)
  6169.  
  6170. Registers on return:    AX    Error code (only if error occurs.
  6171.  
  6172. Flags affected:        Carry    Set if error occurs.
  6173.  
  6174. Possible errors:    AryBadDV
  6175.             AryNull
  6176.  
  6177. Example of Usage:
  6178.             les    di, DVPtr
  6179.             AryClr
  6180.             jc    Error
  6181.  
  6182. Description:    
  6183.  
  6184.   AryClr stores zeros into each data byte of the array.  For most data types
  6185. this corresponds to the value zero (or false, in the case of booleans).
  6186.  
  6187. include: stdlib.a
  6188.  
  6189.  
  6190. Routine:  VectGet (b,w,d)
  6191. -------------------------
  6192.  
  6193. Category:        SmartArray
  6194.  
  6195. Registers on entry:    ES:DI    Points at a SmartArray DV (source)
  6196.             BX    Index into array
  6197.  
  6198. Registers on return:    AL    Contains byte value (VectGetb)
  6199.             AX    Contains word value (VectGetw)
  6200.             DX:AX    Contains dword value (VectGetd)
  6201.             AH    Error code if error occurs
  6202.  
  6203. Flags affected:        Carry    Set if error occurs.
  6204.  
  6205. Possible errors:    AryBadDV
  6206.             AryNull
  6207.             AryBounds
  6208.             AryTypeMismatch
  6209.  
  6210. Example of Usage:
  6211.             les    di, DVPtr
  6212.             mov    bx, i
  6213.             VectGetw
  6214.             jc    Error
  6215.  
  6216. Description:    
  6217.  
  6218.   VectGet(b,w,d) extracts a single element from a one-dimensional array.  It
  6219. returns values for arrays whose element size is 1, 2, or 4 bytes long.  If the
  6220. array element size does not match the call, the routine returns an 
  6221. AryTypeMismatch error.  If BX (containing the index) is not in the range
  6222. 0..Max-1 then VectGet returns an AryBounds error.
  6223.  
  6224. include: stdlib.a
  6225.  
  6226.  
  6227. Routine:  MatGet (b,w,d)
  6228. ------------------------
  6229.  
  6230. Category:        SmartArray
  6231.  
  6232. Registers on entry:    ES:DI    Points at a SmartArray DV (source)
  6233.             BX    Row index into array
  6234.             CX    Column index into array
  6235.  
  6236. Registers on return:    AL    Contains byte value (MatGetb)
  6237.             AX    Contains word value (MatGetw)
  6238.             DX:AX    Contains dword value (MatGetd)
  6239.             AH    Error code if error occurs
  6240.  
  6241. Flags affected:        Carry    Set if error occurs.
  6242.  
  6243. Possible errors:    AryBadDV
  6244.             AryNull
  6245.             AryBounds
  6246.             AryTypeMismatch
  6247.  
  6248. Example of Usage:
  6249.             les    di, DVPtr
  6250.             mov    bx, i
  6251.             mov    cx, j
  6252.             Matgetb
  6253.             jc    Error
  6254.  
  6255. Description:    
  6256.  
  6257.   MatGet(b,w,d) extracts a single element from a two-dimensional array.  It
  6258. returns values for arrays whose element size is 1, 2, or 4 bytes long.  If the
  6259. array element size does not match the call, the routine returns an 
  6260. AryTypeMismatch error.  If BX (containing the index) is not in the range
  6261. 0..Dim1-1 then MatGet returns an AryBounds error.  Likewise, if CX is not in the
  6262. range 0..Dim2-1, you get an AryBounds error.  If the array is not a two-
  6263. dimensional array, MatGet returns an AryBadDV error.
  6264.  
  6265. include: stdlib.a
  6266.  
  6267.  
  6268. Routine:  AryGet (b,w,d) (2)
  6269. ----------------------------
  6270.  
  6271. Category:        SmartArray
  6272.  
  6273. Registers on entry:    ES:DI    Points at a SmartArray DV (source)
  6274.             DX:SI    Points at an index list (see below)
  6275.  
  6276. Registers on return:    AL    Contains byte value (AryGetb)
  6277.             AX    Contains word value (AryGetw)
  6278.             DX:AX    Contains dword value (AryGetd)
  6279.             AH    Error code if error occurs
  6280.  
  6281. Flags affected:        Carry    Set if error occurs.
  6282.  
  6283. Possible errors:    AryBadDV
  6284.             AryNull
  6285.             AryBounds
  6286.             AryTypeMismatch
  6287.  
  6288. Example of Usage:
  6289.  
  6290.     Indices        dw    0,1,2,3
  6291.              .
  6292.              .
  6293.              .
  6294.             les    di, DVPtr
  6295.             mov    dx, seg indices
  6296.             mov    si, offset indices
  6297.             AryGetd
  6298.             jc    Error
  6299.              .
  6300.              .
  6301.              .
  6302.             les    di, DVPtr
  6303.             mov    dx, word ptr indicesDV+2
  6304.             mov    si, word ptr indicesDV
  6305.             AryGetd2
  6306.             jc    Error
  6307.  
  6308. Description:    
  6309.  
  6310.   AryGet is used to extract an element of an arbitrary sized array (it even
  6311. works for one and two dimensional arrays).  On entry, ES:DI points at the
  6312. dope vector for the array and DX:SI points at the array indices.  If you are
  6313. using AryGetb, AryGetw, or AryGetd then DX:SI must point at a word array of
  6314. indices with the first word containing the the first index, the second word
  6315. containing the second index, etc.  Note that DX:SI does *not* contain the
  6316. address of a SmartArray dope vector.  It is simply the address of a simple
  6317. array of values.
  6318.  
  6319.   AryGetx2 is similar to AryGetx except the indices come from a SmartArray
  6320. vector (one-dimension array) rather than from a plain array.  This allows you
  6321. to manipulate the indices of a SmartArray using SmartArray operations.
  6322.  
  6323.   Returned error codes are the same as for VectGet and MatGet.
  6324.  
  6325. include: stdlib.a
  6326.  
  6327.  
  6328. Routine:  VectPut (b,w,d)
  6329. -------------------------
  6330.  
  6331. Category:        SmartArray
  6332.  
  6333. Registers on entry:    ES:DI    Points at a SmartArray DV
  6334.             BX    Index into array
  6335.             AL    Contains byte value (VectPutb)
  6336.             AX    Contains word value (VectPutw)
  6337.             DX:AX    Contains dword value (VectPutd)
  6338.  
  6339. Registers on return:    AH    Error code if error occurs
  6340.  
  6341. Flags affected:        Carry    Set if error occurs.
  6342.  
  6343. Possible errors:    AryBadDV
  6344.             AryNull
  6345.             AryBounds
  6346.             AryTypeMismatch
  6347.  
  6348. Example of Usage:
  6349.             les    di, DVPtr
  6350.             mov    bx, i
  6351.             mov    ax, 0
  6352.             VectPutw
  6353.             jc    Error
  6354.  
  6355. Description:    
  6356.  
  6357.   VectPut(b,w,d) stores a value into an element of a one-dimensional array.  It
  6358. works for arrays whose element size is 1, 2, or 4 bytes long.  If the
  6359. array element size does not match the call, the routine returns an 
  6360. AryTypeMismatch error.  If BX (containing the index) is not in the range
  6361. 0..Max-1 then VectPut returns an AryBounds error.
  6362.  
  6363. include: stdlib.a
  6364.  
  6365.  
  6366. Routine:  MatPut (b,w,d)
  6367. ------------------------
  6368.  
  6369. Category:        SmartArray
  6370.  
  6371. Registers on entry:    ES:DI    Points at a SmartArray DV
  6372.             BX    Row index into array
  6373.             CX    Column index into array
  6374.             AL    Contains byte value (MatPutb)
  6375.             AX    Contains word value (MatPutw)
  6376.             DX:AX    Contains dword value (MatPutd)
  6377.  
  6378. Registers on return:    AH    Error code if error occurs
  6379.  
  6380. Flags affected:        Carry    Set if error occurs.
  6381.  
  6382. Possible errors:    AryBadDV
  6383.             AryNull
  6384.             AryBounds
  6385.             AryTypeMismatch
  6386.  
  6387. Example of Usage:
  6388.             les    di, DVPtr
  6389.             mov    al, 25
  6390.             mov    bx, i
  6391.             mov    cx, j
  6392.             Matputb
  6393.             jc    Error
  6394.  
  6395. Description:    
  6396.  
  6397.   MatPutx (x=b, w, d) stores the value in AL, AX, or DX:AX into a two-
  6398. dimensional array at the indices specified by (BX,CX).  The code returns
  6399. all the appropriate errors in the event of a mistake.  Otherwise, this
  6400. routine is quite similar to the VectPutx routine.
  6401.  
  6402. include: stdlib.a
  6403.  
  6404.  
  6405. Routine:  AryPut (b,w,d)
  6406. ------------------------
  6407.  
  6408. Category:        SmartArray
  6409.  
  6410. Registers on entry:    ES:DI    Points at a SmartArray DV
  6411.             DX:SI    Points at an index list (see below)
  6412.             AL    Contains byte value (AryPutb)
  6413.             AX    Contains word value (AryPutw)
  6414.             BX:AX    Contains dword value (AryPutd)
  6415.  
  6416. Registers on return:    AH    Error code if error occurs
  6417.  
  6418. Flags affected:        Carry    Set if error occurs.
  6419.  
  6420. Possible errors:    AryBadDV
  6421.             AryNull
  6422.             AryBounds
  6423.             AryTypeMismatch
  6424.  
  6425. Example of Usage:
  6426.  
  6427.     Indices        dw    0,1,2,3
  6428.              .
  6429.              .
  6430.              .
  6431.             mov    ax, word ptr ddval
  6432.             mov    bx, word ptr ddval+2
  6433.             les    di, DVPtr
  6434.             mov    si, offset Indices
  6435.             mov    dx, seg Indices
  6436.             AryPutd
  6437.             jc    Error
  6438. Description:    
  6439.  
  6440.   You use AryPut to store values into a SmartArray.  This routine lets you
  6441. store bytes, words, and double words into a SmartArray.  On entry, ES:DI
  6442. points at the dope vector for the specified SmartArray.  DX:SI points at
  6443. a list (simple linear array, not a SmartArray) of index values.  AL, AX, or
  6444. BX:AX contains the byte, word, or double word values to store at the specified
  6445. array element.  Note that BX:AX holds the dword value, *not* DX:AX.  DX is
  6446. already in use holding the segment portion of the index array.
  6447.  
  6448. include: stdlib.a
  6449.  
  6450.  
  6451. Routine:  VectLEA
  6452. -----------------
  6453.  
  6454. Category:        SmartArray
  6455.  
  6456. Registers on entry:    ES:DI    Points at a SmartArray DV
  6457.             BX    Index into vector
  6458.  
  6459. Registers on return:    ES:DI    Points at specified element
  6460.             AH    Error code if error occurs
  6461.  
  6462. Flags affected:        Carry    Set if error occurs.
  6463.  
  6464. Possible errors:    AryBadDV
  6465.             AryNull
  6466.             AryBounds
  6467.  
  6468. Example of Usage:
  6469.  
  6470.             les    di, AryPtr1
  6471.             mov    bx, i
  6472.             VectLEA
  6473.             jc    Error
  6474.  
  6475. Description:    
  6476.  
  6477.   The VectGetx, MatGetx, AryGetx, VectPutx, MatPutx, and AryPutx routines all
  6478. have one major drawback-- they're limited to processing array with bytes, words,
  6479. and double words as elements.  They do not allow access to other types.
  6480. Unfortunately, it is not possible to supply routines to fetch and store every
  6481. possible type of array element since these are user definable.  Instead, the
  6482. SmartArray package provides a routine which returns the *address* of an arbi-
  6483. trary array element.  Then the calling code may manipulate it as desired.
  6484.  
  6485. VectLEA lets you obtain the address of an element in an arbitrary typed single
  6486. dimension array.  You pass the index of the desired element in BX and a pointer
  6487. to the SmartArray DV in ES:DI.  It returns a pointer to the desired element
  6488. in ES:DI.
  6489.  
  6490. include: stdlib.a
  6491.  
  6492.  
  6493. Routine:  MatLEA
  6494. ----------------
  6495.  
  6496. Category:        SmartArray
  6497.  
  6498. Registers on entry:    ES:DI    Points at a SmartArray DV
  6499.             BX    Row index into matrix
  6500.             CX    Column index into matrix
  6501.  
  6502. Registers on return:    ES:DI    Points at specified element
  6503.             AH    Error code if error occurs
  6504.  
  6505. Flags affected:        Carry    Set if error occurs.
  6506.  
  6507. Possible errors:    AryBadDV
  6508.             AryNull
  6509.             AryBounds
  6510.  
  6511. Example of Usage:
  6512.  
  6513.             les    di, AryPtr1
  6514.             mov    bx, i
  6515.             mov    cx, j
  6516.             MatLEA
  6517.             jc    Error
  6518.  
  6519. Description:    
  6520.  
  6521. MatLEA lets you obtain the address of an element in an arbitrary typed two
  6522. dimensional array.  You pass the index of the desired element in BX and a
  6523. pointer to the SmartArray DV in ES:DI.  It returns a pointer to the desired
  6524. element in ES:DI.
  6525.  
  6526. include: stdlib.a
  6527.  
  6528.  
  6529. Routine:  AryLEA
  6530. ----------------
  6531.  
  6532. Category:        SmartArray
  6533.  
  6534. Registers on entry:    ES:DI    Points at a SmartArray DV
  6535.             DX:SI    Pointer to index list.
  6536.  
  6537. Registers on return:    ES:DI    Points at specified element
  6538.             AH    Error code if error occurs
  6539.  
  6540. Flags affected:        Carry    Set if error occurs.
  6541.  
  6542. Possible errors:    AryBadDV
  6543.             AryNull
  6544.             AryBounds
  6545.  
  6546. Example of Usage:
  6547.  
  6548.     indices        dw    0,2,3,1
  6549.              .
  6550.              .
  6551.              .
  6552.             les    di, AryPtr1
  6553.             mov    dx, seg indices
  6554.             mov    si, offset indices
  6555.             AryLEA
  6556.             jc    Error
  6557.  
  6558. Description:    
  6559.  
  6560. AryLEA lets you obtain the address of an element in an arbitrary multi-
  6561. dimensional array.  DX:SI points at the index array (see AryPut & AryGet for
  6562. details).  AryLEA returns the address of the specified element in ES:DI.
  6563.  
  6564. include: stdlib.a
  6565.  
  6566.  
  6567. Routine:  VectOuter
  6568. -------------------
  6569.  
  6570. Category:        SmartArray
  6571.  
  6572. Registers on entry:    ES:DI    Points at a SmartArray DV (1st operand)
  6573.             DX:SI    Pointer at a SmartArray DV (2nd operand)
  6574.             CS:IP    Pointer to handler routine (if opcode is 0)
  6575.             AH    Opcode
  6576.  
  6577. Registers on return:    ES:DI    Points at result matrix
  6578.             AH    Error code if error occurs
  6579.  
  6580. Flags affected:        Carry    Set if error occurs.
  6581.  
  6582. Possible errors:    AryBadDV
  6583.             AryNull
  6584.             AryOverflow
  6585.             AryDiv0
  6586.             AryMemory
  6587.  
  6588. Example of Usage:
  6589.  
  6590.             les    di, Vect1Ptr
  6591.             mov    dx, seg Vect2
  6592.             mov    si, offset Vect2
  6593.             mov    ah, vopPlus
  6594.             VectOuter
  6595.             jc    Error
  6596.  
  6597. Description:    
  6598.  
  6599.   VectOuter performs an outer product on two vectors.  If "op" represents an
  6600. operation, then the outer product of v1 and v2 is the following:
  6601.  
  6602.             v2[0]        v2[1]        ...        v2[n-1]
  6603.  
  6604.     v1[0]    v1[0] op v2[0]        v1[0] op v2[1]  ...    v1[0] op v2[n-1]
  6605.  
  6606.     v1[1]    v1[1] op v2[0]        v1[1] op v2[1]  ... v1[1] op v2[n-1]
  6607.       .
  6608.       .
  6609.       .
  6610.     v1[n-1]    v1[n-1] op v2[0]    v1[n-1] op v2[1]... v1[n-1] op v2[n-1]
  6611.  
  6612.  
  6613.   The actual operation performed is specified in one of two ways, either by
  6614. a numeric opcode in AH upon entry to the routine or via a user-supplied
  6615. routine.  Currently, the following opcodes are predefined in the system:
  6616.  
  6617.     vopUser        =    0
  6618.     vopPlus        =    2
  6619.     vopMinus    =    4
  6620.     vopMul        =    6
  6621.     vopDiv        =    8
  6622.     vopMod        =    10
  6623.     vopAnd        =    12
  6624.     vopOr        =    14
  6625.     vopXor        =    16
  6626.     vopEQ        =    18
  6627.     vopNE        =    20
  6628.     vopGE        =    22
  6629.     vopGT        =    24
  6630.     vopLT        =    26
  6631.     vopLE        =    28
  6632.     vopMin        =    30
  6633.     vopMax        =    32
  6634.  
  6635.  
  6636.   The result produced is always an m x n matrix where m is the size of the
  6637. first vector and n is the size of the second vector.  If the opcode is zero
  6638. (vopUser) then the call to VectOuter takes the following form:
  6639.  
  6640.         mov    ah, vopUser
  6641.         VectOuter
  6642.         dd    MyOperation
  6643.  
  6644. An address must immediately follow the call to the VectOuter routine.  You must
  6645. supply this address (and the corresponding routine).  On entry to this routine
  6646. DS:SI points at the first operand and ES:DI points at the second.  The user
  6647. routine should perform the operation and store the result at DS:SI.  Also upon
  6648. entry, AL contains the element size and AH contains the element type.  The
  6649. user routine is responsible for error checking.  If an error occurs, it should
  6650. set the carry flag and return the error code in AH.
  6651.  
  6652. Please note that the built in operations only support 1, 2, and 4 byte unsigned
  6653. and signed integers.  Floating point operations will follow soon.
  6654.  
  6655. include: stdlib.a
  6656.  
  6657.  
  6658.  
  6659. AryNoError    =    0            ;Should never occur
  6660. AryTypeMismatch    =    1            ;Array type mismatch
  6661. AryOverflow    =    2            ;Arithmetic overflow
  6662. AryDiv0        =    3            ;Division by zero
  6663. AryIllegalOp    =    4            ;Illegal operation on array
  6664. AryBounds    =    5            ;Array index error
  6665. AryMemory    =    6            ;Memory allocation error
  6666. AryBadDV    =    7            ;Illegal dope vector
  6667. AryNull        =    8            ;Null pointer to array data
  6668.  
  6669.